Flex 4, asdoc and custom tags

Today I decided to update to flex 4. After installing version 4.1.0.16076 I ran asdoc to see if the comments in my action script library still were ok. Things had changed though, as I discovered. Below I describe my experience and solution.

Since I’m sending out my library with various project sources I have included a standard header that includes author, website, copyright, version, etc. information. Since there were no comment tags for those, I used some HTML formatting to get a style similar to the rest of the generated documentation.

However after running asdoc from flex 4, part of this formatting had disappeared. The various <br/> tags I used had been filtered out; asdoc also removed style attributes I used within some <span> tags.

Not being a xslt guru and not really wanting to dive into over 300kb of almost completely undocumented xslt code I looked around the internet for a solution.

First I came across asdoc-enhancements. Originally intended for flex 3, I managed to get it working with flex 4. I looked in the downloaded class-files.xslt and then copied the warning code to the new class-files.xslt. I only had to change customs/warning to prolog/asCustoms/warning.

I added a @warning to both my class comment as well to a method comment. After running asdoc, the generated html got a nice red Warning text line at both comments.

So I decided to try to add another custom tag. But this did not work out completely as expected, although the new tag was shown; the @warning tag no longer produced a red Warning text line.

So I looked at the generated xml files (using the -keep-xml option). In some of the generated xml files the warning tag had disappeared. After some digging around, I found the java source at TopLevelClassesGenerator.java. It turns out the method processCustoms() only stores the last custom tag it comes across; instead of storing all.

So it seems you can have a custom tag, but only one 🙁

However not all was lost, it is still possible to use xml tags as value for the custom tag. These will appear as child elements of the custom tag element in the generated xml files.

So instead of various custom tags I defined a single custom tag (@ultraforce), with various xml tags as value. And then alter the class-files.xslt to transform those into formatted HTML.

Here is how it looks inside an .as file:

  /**
   * ...
   * @ultraforce
   * <author email="josha_at_ultraforce.com">J. Munnik</author>
   * <website>www.ultraforce.com</website>
   * <copyright>Copyright (c) 2008 by Ultra Force Development</copyright>

And this is what I added to the end of <xls:template name="description"> in the class-files.xslt (this is my first try at xslt programming, so don’t expect to much):

<xsl:if test="prolog/asCustoms/ultraforce/author">
  <p><b>Author</b><br/><xsl:value-of select="prolog/asCustoms/ultraforce/author/." />
  <xsl:if test="prolog/asCustoms/ultraforce/author/@email">
    <xsl:variable name="email" select="replace(prolog/asCustoms/ultraforce/author/@email, '_at_', '@')" />
    <xsl:value-of disable-output-escaping="yes" select="concat(' (&lt;a href=&quot;mailto:',$email,'&quot; target=&quot;_blank&quot;&gt;',$email,'&lt;/a&gt;)')"/>
  </xsl:if>
  </p>
</xsl:if>
<xsl:if test="prolog/asCustoms/ultraforce/website">
  <xsl:variable name="website" select="prolog/asCustoms/ultraforce/website/." />
  <p><b>Website</b><br/>
  <xsl:value-of disable-output-escaping="yes" select="concat('&lt;a href=&quot;http://',$website,'&quot; target=&quot;_blank&quot;&gt;',$website,'&lt;/a&gt;')"/>
  </p>
</xsl:if>
<xsl:if test="prolog/asCustoms/ultraforce/copyright">
  <p><b>Copyright</b><br/>
  <xsl:value-of disable-output-escaping="yes" select="replace(prolog/asCustoms/ultraforce/copyright/., '\(c\)', '&amp;copy;')" />
  </p>
</xsl:if>

After asdoc, the extra information is formatted correct again. And I have to admit this new way of specifying information is at least more readable in the source then the previous one using HTML formatting.

Still, to bad asdoc does not support multiple custom tags or even better yet, defines various new tags. But who knows, maybe in the future things might change…

Note: it seems the @author tag is supported by the java code and results in a separate element in the generated xml files. So one only has to add a transformation to class-files.xslt to make it visible.

Weakly referenced listeners

I never paid a lot of attention to the 5th parameter of addListener, the useWeakReference parameter.

But the other day I decided to play a bit with it. As a reminder of its function I created a small test.

To create it yourself, perform the following steps:
1. Create new AS3 movieclip in Flash IDE
2. Set framerate to 1 fps
3. Copy following code in the first frame:

// create two event listener objects
var bot1: Object = {
  spam: function(anEvent: Event): void 
  {
    trace('bot1: spam');
  }
};
var bot2: Object = {
  spam: function(anEvent: Event): void 
  {
    trace('bot2: spam');
  }
};
// call spam every frame
this.addEventListener(
  Event.ENTER_FRAME, bot1.spam, false, 0, false
);
this.addEventListener(
  Event.ENTER_FRAME, bot2.spam, false, 0, true
);
// frame counter
var frame: int = 1;
// perform different action every frame
function demo(anEvent: Event): void
{
  switch(frame)
  {
    case 1:
    case 3:
      trace('Garbage collecting');
      System.gc();
      break;
    case 2:
      trace('Removing reference');
      bot1 = null;
      bot2 = null;
      break;
    case 4:
      trace('Removing demo');
      this.removeEventListener(Event.ENTER_FRAME, demo);
      break;
  }
  frame++;
}
// call demo every frame
trace('Adding demo');
this.addEventListener(Event.ENTER_FRAME, demo);

Even though the reference to bot1 is cleared, you will still see trace messages with “bot1: spam”; because there is still a reference to the spam listener method inside bot1. So bot1 does not get removed by the garbage collector.

Flash quirks: SimpleButton can be a DisplayObject.parent

While developing a custom cursor class I came across the following quirk.

One of the things the custom cursor class does is checking if mouseChildren of all parent DisplayObjectContainer instances are enabled.

It retrieves the current objects under the mouse via this.stage.getObjectsUnderPoint and recursively processes the parent properties till the stage instance is reached.

The quirk happens when you mouse over a SimpleButton on the stage which might contain Shape and TextField instances. The parent property of those will be set to SimpleButton instance. The problem is that SimpleButton is not a DisplayObjectContainer subclass, but instead is a subclass of InteractiveObject. So there is no mouseChildren property to access.

With my current Flash and Firefox versions, trying to access this property resulted in the Flash player plugin crashing within FireFox.

To prevent this, check first if the parent is indeed a DisplayObjectContainer instance.