Archive for the 'flex' Category

FlexChart Updates

The past month or so has seen quite a few improvements and bug fixes to FlexChart, though I haven't blogged about any of them.  Most notably, there was a weird NPE that manifested itself when loading a Pie chart via FlashVars.  For some unknown reason, Flex/Flash didn't give any indication the error was occurring, it just silently terminated the active call stack and continued on it's merry way.  This left the app in a quasi-broken state that would prevent certain future calls from working, but allowing others to execute without issue.  I still have no explanation as to why the error silently terminated, but I've since seen the same behaviour inside FDS, so it's not charting specific.

The ability to style charts has been extended a bit, though it's still not as highly polished as I could wish.  For example, supplying a stroke weight for a line series causes the stroke color to default to black, instead of the automatically assigned color (orange, green, blue, …).  In the reverse case, if you supply custom colors on a Pie chart, they render correctly, but the legend (if one is used) uses the default colors (orange, green, blue, …).  Gradient fills are now available as well.

I've also improved handling of empty charts.  The stock custom tag requires a descriptor, but if you don't have data at page render time, you usually end up providing "<chart />" as the descriptor.  The engine now detects this case (whether on the initial load or later passed in), and is a bit more intelligent about ensuring it clears it's stage.  Previously you could end up with an empty CartesianChart in some cases.

Finally, I made a number of improvements to performance and handling of data values.  This was mostly accomplished by explicitly converting the XML nodes into real objects for the chart to render, rather than using the XML directly.  There were some implicit type conversions that didn't happen consistently out of XML nodes, but work fine out of generic objects.

And Again!

Another update to FlexChart this evening, providing set and series colors (both fills and strokes), an option for including/excluding the legend when exporting a chart to PNG, and a few new examples showcasing the features (including some really ugly developer art).

With the coloring support, the 'Grouped Series' example makes a lot more visual sense, so if you thought WTF yesterday, go look at it again.  ;)

More FlexCharts Goodness

Another batch of changes to FlexChart.

First is grouped series, which is hard to explain, but easy to understand.  Go hit the demo and select "Grouped Series" from the dropdown.  The chart layout has always been possible, but the legend just displayed a flat series list with no awareness of the groupings.  To see the old behaviour, change the 'legendStyle' attribute of the chart tag to "simple", and hit "Update Chart".

Second is direct support for PNG exports of the chart.  A Base64-encoded PNG can be requested via an ExternalInterface callback which you can then do whatever you want with.  The demo app just sends it server side (in a new window) for deserialization with CFIMAGE and immediately sends it back to the client.  Hardly interesting, but definitely illustrative.

Finally, I've abandoned the compile-in-page model, Flex SDK 2.0.1, and a single file architecture completely.  You can drop the binary anywhere you want without any dependency on FlexBuilder, a Flex SDK, or any server component, which is nice.  Of course, if you want to customize, it required FlexBuilder 3.  I think that's the right tradeoff.  I've also started splitting up the engine for easier maintenance, now that there's no need to keep it single file (which there was when it was server-compiled).  I haven't done much, but that'll come.  Definitely make it easier to work with.

Soon to come down the pipe are custom colors for series and sets, support for multiple y-axes, and a grid legend style which is basically a headerless datagrid under the chart with a row per series and a column per x-axis item, all lined up evenly.

FlexChart Update

Long time no blog…  I've updated my FlexChart component slightly, as well as repackaged it for easier consumption.  The new feature is the availability of a 'dataTipFunction' attribute on the root 'chart' element, which will be called to format data tips.  It gets passed an object with various keys about the backing chart item.  Since that's all it gets (rather than a HitData instance), it's not as powerful as the native Flex capabilities, but it gets the job done with pure JS.

The repackaging was to a binary (precompiled) format, rather than requiring the server compilation I'd originally built it with.  The old style is still available where it always has been, but the preferred usage is now either the distribution directory (svn) or the FlexBuilder project itself.  With the new model, you just drop the compiled binaries (yours or mine) into any web-accessible directory and use them, regardless of whether you have LCDS installed to do the compilation.

New FlexChart Demo

I've updated the FlexChart demo to include display of the descriptor XML that is loaded into the chart, as well as providing a way to edit the XML inline and load your modified XML into the chart client-side.  In addition to being far easier to experiment with, it also showcases the the client-side redrawing of the chart and gives a hit of how powerful the engine can be within a JS UI.

Doing it this way means I lost the demo of having the chart request a new descriptor from the server-side on it's own, but the client-side descriptor injection is a "neater" capability, I think.   I haven't posted an updated zip of the source (including the demo app), but it's available from Subversion at the URL listed at the bottom of the demo.

Clickable FlexCharts

I just updated FlexChart with a 'click' callback.  You can now specify the name of a JavaScript function to be invoked when a data point on the chart is clicked.  The function is passed the ID of the chart, the series label, and the x and y values for the point, in that order.  Check the demo (which just pops an alert) to see it in action.

What is this good for, you ask?  Everything that CFCHART's 'url' attribute was theoretically good for, except it's actually useful.  If you wan CFCHART's behaviour, just have your callback do a window.location.  For those of us that don't, you can use the parameters to AJAX in some related content to another section of the page, compute and inject a new descriptor do do "drill-down" within the same chart instance, or any number of other things.  Lots of possibilities.

More Flex Chart Goodness

This evening, I extended my Flex charting widget further.  The demo is still available, and I've posted a new ZIP archive of the source.   Here's a quick rundown of what's changed:

  • The custom tag is now called xmlchart.cfm, instead of just chart.cfm.  That's to make way for a different chart.cfm that provides an XML-less interface (like CFCHART does) that will internally build the XML and then hand it off to xmlchart.cfm.
  • Category and DateTime axes are now supported.  The only gotcha is that you must supply a milliseconds-since-epoch value for your timestamps.  It's XML, not real objects, and the serialization/deserialization doesn't work right with native dates.
  • Pie charts are now available.
  • Legend placement is now customizable (top, bottom, left, right, none).
  • Axes can have a title set for them, and they can be positioned on either edge of the chart (top/bottom for x, left/right for y).
  • The descriptor language has changed significantly:
    • The x- and y-axis now have their own element under the chart element.
    • All series and sets are now contained with a new data element under the chart element.
    • There are only series and set elements now, and both take a type attribute for determining what type of series/set they are.  Series implicitly inherit their type from the containing set, if present, otherwise their type must be specified.

At this point, I'm pretty much done developing, and I'm on to using it.  I did one app as a proof of concept and it works great.  I'll be doing some more shortly.

And Happy Thanksgiving, at least for all you US folks.

My Flex-based Chart Engine

I've been looking for a good charting mechanism for a few personal apps.   CFCHART works in some cases, but I usually opt for SVG, either rendered inline (i.e. SVG and XHTML interleaved in an XML doc) or rasterized into a PNG server-side via Batik.  Both solutions have their merits, but both also have a lot of problems (drawing SVG requires a lot of arcane math, and CFCHART is quite inflexible and has a number of bugs).

At work, I've been doing quite a bit of work with the Flex Charting components, and I got to thinking that a generic chart that could be parameterized with both data and structure wouldn't be too hard to build, but never really did anything about it.  Then today Koen, Joshua, and I were talking about something or other and somehow ended up with me mentioning you could inline your MXML with a JSP taglib and have a Flex movie spit out in your page (much as CFCHART does it).  I threw together a little proof of concept, and digging in a little deeper with flashvar parameterization, realized that you could do some pretty sweet stuff with it.

I kept playing a bit, and started building some generic charting stuff, and this is what I ended up with.  It takes a descriptor XML document either as a literal or a URL, supplied via flashvars or via ExternalInterface callbacks, and will draw a chart based on it.  The descriptor is just that, a complete description of the chart to render, both data and structure.  There's a link to the descriptor on the demo page, so you can see it.  The flexibility is pretty limited (for example, you can't disable the legend), but all that stuff would be pretty simple to add down the road.

The engine only supports Cartesian charts, and only numeric data (linear or logarithmic), but that covers the vast majority of charts, at least for me.  It'd be fairly trivial to extend it to support category and/or datetime axes, I just didn't do it.  The non-Cartesian charts (e.g. pie charts) would be a little more work, as they're pretty fundamentally different, but it should be a backwards compatible change (i.e. strictly additive changes to the descriptor language).

I've made a ZIP of the demo app, including the custom tag wrapper and the MXML source.  For the runtime compilation via the JSP taglib, you have to have Flex on your server.  If you've got CF8 with LCDS, you're set.  I'm not sure about other configurations, but I know the JSP taglib has been around for a while, so I'd expect it to work other places as well (though you might need to tweak).

The runtime compilation is not at all required for the engine to work, it's just an easy way to package it because the taglib takes care of generating all the wrapper HTML/JS.  If you don't mind writing that yourself, you can use the SWF directly.

Also, the SWF is compiled with Flex SDK 2.0.1, because that's what CF's LCDS uses.  Among other things, that means you don't get "grouped" ColumnSets, because those are new in Flex 3.  The MXML will recompile as-is with SDK 3 (e.g. in FlexBuilder), and then you'll be able to use "grouped", but the runtime compilation won't do that unless you upgrade the internal SDK.

Enums and ActionScript's Static Initializers

I discovered today, while trying to synthesize an Enum type, that AS3 has the concept of a static initializer, which is awesome. In a nutshell, a static initializer is kind of like a constructor, but it's for the class object itself, not instances of the class. It gets invoked during classloading, after all static properties have been set, but the class is turned loose for general consumption. Here's an example of an Enum type (named ColorEnum) that uses the static initializer (in bold):

package com.barneyb.test {

  public class ColorEnum {

    public static const BLACK:ColorEnum = new ColorEnum(0x000000);
    public static const WHITE:ColorEnum = new ColorEnum(0xFFFFFF);

    private static var locked:Boolean = false;

    {
      locked = true;
    }

    private var _color:uint;
    public function get color():uint {
      return _color;
    }

    public function ColorEnum(color:uint) {
      if (locked) {
        throw new Error("You can't instantiate ColorEnum");
      }
      _color = color;
    }
  }
}

What this provides is a ColorEnum class that cannot be instantiated, with two instances stored in the BLACK and WHITE static constants. This sort of class locking is equally useful for singletons (think ServiceLocator if you use Cairngorm, though they implement it differently). Usually, you use a private constructor for this type of behaviour, but since AS3 doesn't support that, you have to synthesize it. However, that's not all a static initializer can do.

Another use case is if you have a complex static variable that you need to initialize, but can't do in a single expression. For example, if you need to create multiple aggregated objects, you usually need multiple expressions. You can do this in a static initializer as well. Note that you can't set a static const within a static initializer, but you can set a static var (variables).

Interesting ChangeWatcher Behaviour

I've been working on a Flex app for visualizing market research data for the past week or two, and ran into an interesting behaviour of ChangeWatcher, quite at odds with how I'd have expected it to work.  As everyone knows, the Flash player is single threaded (and frame based), which makes for some interesting edge cases.  Part of that single threading is that each individual function invocation always happens within a single thread of execution, all within a single frame, and without any interleaving of other processing.  In simpler terms, a function always starts at the top and goes to the end, with sole control over the AVM. Events are handled, not as separate threads, but as a queue that gets processed at certain points (presumably the entry and/or exit of each frame).

With the ChangeWatcher, you can "watch" a given object property, and have a passed function (usually a closure) invoked when the property is reset.  Here's a simple example:

ChangeWatcher.watch(myObject, "nameArray", function(...args):void {
  Alert.show("myObject.nameArray was reset to " + myObject.nameArray);
});

That's all well and good, but what is interesting is that it happens as part of invoking the 'nameArray' setter on 'myObject'.  Note that the setter exists whether it's implicit or explicit.  I expected the callback to be event based, so the setter would execute and dispatch an event to be resolved at a later time.  It doesn't do that, the callback actually happens as part of the setter's execution.  This seems at odds with the event-driven nature of the Flash player.  Why does this matter, you ask?  Here's an example (assumed to be a method of the 'myObject' instance from above):

function doSomething():void  {
  nameArray = [];
  nameArray.push("barney");
  nameArray.push("heather");
}

I expected the behaviour of invoking 'doSomething' to go like this:

  1. set nameArray to a new Array instance
    1.  dispatch a change event to the change watcher
  2. add "barney"
  3. add "heather"
  4. return
  5. the event is received
  6. the ChangeWatcher callback is invoked (Alert "barney, heather")

However, because it's not event driven, that's not what happens.  Here's the actual behaviour:

  1. set nameArray to a new Array instance
  2. invoke the ChangeWatcher callback (Alert "")
  3. add "barney"
  4. add "heather"
  5. return

If you want the former behaviour, you have to reimplement the 'doSomething' method like this:

function doSomething():void  {
  var a:Array = [];
  a.push("barney");
  a.push("heather");
  nameArray = a;
}

That will give the desired behaviour, because when the watched setter is invoked, the array is already fully populated.  In this particular case (a contrived example), you could also do it this way:

function doSomethind():void {
  nameArray = [ "barney", "heather" ];
}

That's not going to be possible in a lot of cases, however.