Saturnboy
 10.23
Code
off

Since Flex is Dead, I decided to rebuild my fancy Flex Clock using the html5 canvas element. Here is the result:

(click to see it in action)

Lots of very vanilla drawing code that is fairly boring, but one interesting part is how the new canvas-based clock uses svg paths. The old flex code used svg paths liberally as simple way to draw shapes, but since canvas doesn’t support drawing svg path data directly I had to write my own:

function drawPath(ctx,path,fill,ang) {
    ctx.save();
    ctx.rotate(ang == undefined ? 0 : ang  * Math.PI / 180.0);
    ctx.beginPath();
 
    var parts = path.split(' ');
    while (parts.length > 0) {
        var part = parts.shift();
        if (part == 'M') {
            coords = parts.shift().split(',');
            ctx.moveTo(coords[0], coords[1]);
        } else if (part == 'L') {
            continue;
        } else if (part == 'Z') {
            break;
        } else if (part.indexOf(',') >= 0) {
            coords = part.split(',');
            ctx.lineTo(coords[0], coords[1]);
        }
    }
 
    ctx.closePath();
    ctx.fillStyle = (fill == undefined ? '#000' : fill);
    ctx.fill();
    ctx.restore();
}

The drawPath() function takes svg path data as input (with the restriction that it contains only M (move to), L (line to), and Z (close path) elements), and executes moveTo() and lineTo() calls in the canvas element instead. It does zero error checking, so the incoming svg path data must be well formatted.

If you call it like this:

drawPath(ctx, 'M 0,0 L 0,10 10,10 10,0 Z');

You’d get a nice 10px by 10px square as expected.

Conclusion

It’s no surprise that canvas is just as powerful as Flex or SVG as far as drawing shapes and gradients, but it would definitely make canvas extra cool if it had more intergrated svg path support. Yes, of course, I could have used pure svg if I wanted to draw a bunch of svg shapes, but I had set my mind on using canvas only.

Files

 9.9

Did a little bit of vanilla Flex work recently, and I needed a Tree component to display an object hierarchy. Everyone, by now, hopefully knows that mx:DataGrid and mx:Tree are two of the crappiest, bug ridden, worst performing components from Flex 3. And, everyone by now, has left the buggy world of Flex 3 behind and entered the world Flex 4 and the vastly improved Spark components. With the arrival of Flex 4.5 this summer, Adobe finally gave us a rewritten Spark-based DataGrid. Alas, no updated Tree yet, so I had to write my own. So once again, I turned to the trusty combo of List plus custom ItemRenderer to make pure-Spark custom TreeList component that doesn’t suck.

Alex Harui is the guru of turning a Flex 4 Spark List into a look-alike for the old Flex 3 component using skins and a custom ItemRenderer. Alex has used List + ItemRenderer to make a DataGrid, DateField, ColorPicker, Menu + MenuBar, and even an XML-based TreeList. Unfortunately, Alex’s TreeList assumes incoming XML, and I needed a TreeList that could display a simple object hierarchy (root node with children, and those children have children, etc.). Since I couldn’t find exactly what I wanted, I decided to build it myself.

Flattener

The key step to getting a hierarchy of objects to display as a list is: flatten the list, duh! Or at least flatten the part of the tree you wish to display. So, I built a simple adapter class that turns an object hierarchy into an ArrayList that can be given directly to a List‘s dataProvider.

Here’s the actual flattener, but with just the comments not the code:

public class MyObjFlattenedList extends ArrayList {
 
    //the root object
    private var _root:MyObj;
 
    //list of open nodes
    private var _openList:Array;
 
    public function MyObjFlattenedList(root:MyObj) {
        _root = root;
        _openList = [];
        reset();
        ...
    }
 
    public function reset(openList:Array = null):void {
        //init the flattened list, starting at root
        _openList = (openList == null ? [] : openList);
        var a:Array = [];
        addItemToList(_root, a);
        this.source = a;
    }
 
    private function addItemToList(obj:MyObj, a:Array):void {
        //recursively walk obj and all of its "open" children to build
        //a flattened list that is returned in array a
    }
 
    public function isItemOpen(obj:MyObj):Boolean {
        //true if obj has children and is "open"
    }
 
    public function openItem(obj:MyObj):void {
        //add all of obj's children (if any) to the list
    }
 
    public function closeItem(obj:MyObj):void {
        //remove all of obj's children (if any) from the list
    }
    ...
}

There’s really not much to it. When instantiated with a root object, the object hierarchy is walked recursively to build a flattened list of all the open nodes. Once the initial list is built, openItem() can be called to open a node, and add all its children to the list. Alternately, closeItem() can be called to close a node, and remove all its children from the list.

Design

I used some basic styling and skinning, but the ItemRenderer does the majority of the work. Here’s the abbreviated version of MyObjRenderer.mxml with all the boring stuff edited out:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    width="100%"
    autoDrawBackground="false">
 
    <fx:Script>
        <![CDATA[
            [Bindable] private var _obj:MyObj;
            [Bindable] private var _hasChildren:Boolean = false;
 
            private var _list:MyObjFlattenedList;
 
            override public function set data(val:Object):void {
                super.data = val;
 
                if (val != null) {
                    _obj = val as MyObj;
 
                    var ownerList:List = owner as List;
                    _list = ownerList.dataProvider as MyObjFlattenedList;
 
                    btn.selected = _list.isItemOpen(_obj);
                    _hasChildren = (_obj.children != null && _obj.children.length > 0);
                }
            }
 
            private function toggleHandler():void {
                if (btn.selected) {
                    _list.openItem(_obj);
                } else {
                    _list.closeItem(_obj);
                }
            }
        ]]>
    </fx:Script>
 
    <s:states>
        <s:State name="normal" />
        <s:State name="hovered" />
        <s:State name="selected" />
    </s:states>
 
    <s:Rect ...>
 
    <s:HGroup ...>
        <s:ToggleButton id="btn" click="toggleHandler()" visible="{_hasChildren}" ... />
 
        <s:Group id="dot" visible="{!_hasChildren}" ... />
 
        <s:Label ... />
    </s:HGroup>
</s:ItemRenderer>

Each rendered item has a background Rect and a Label. But most importantly, each row has either a ToggleButton (if the object has children) or some non-interactive visuals (if the object doesn’t have children it just gets a dot). The toggle button is the key interactive element used to open or close the node, everything else is part of the visual gravy added to make the list look good.

Focusing on the functional stuff, if you look in the script block, you’ll see two functions: a data() setter and a toggleHandler() to handle toggle button clicks. As expected, clicking the toggle button calls openItem() or closeItem() on the flattener adapter which adds or removes children from the flattened list, respectively. The setter mostly sets up the local variables, but it notably computes if the object has children or not, and also sets the initial state of the toggle button.

Conclusion

With just a little effort, we can have a nice usable Spark TreeList component that looks decent. More importantly, we have total control and can make the TreeList look like anything our designer can throw at us. As is always the case, the combo of List + ItemRenderer proves to be awesome. I tried to cover all the interesting pieces, but for the details, you’ll need to check out the source code.

Here’s the finished product (view source enabled):

Flash is required. Get it here!

Use it and enjoy.

Files

 11.4

I tried to push my Flex 4 skinning skills to the limit, and the result is a fancy clock skin.

clock
(click to see it in action)

The fancy clock skin overlays a very simple clock component. The Clock component is quite underwhelming, but here it is in all of its abbreviated glory:

public class Clock extends SkinnableComponent {
    public var secAngle:Number = 0.0;
    public var minAngle:Number = 0.0;
    public var hourAngle:Number = 0.0;
    private var _timer:Timer;
    private var _tween:GTween;
 
    public function Clock() {
        ...
        _tween = new GTween(this, 2, ...);
        _timer = new Timer(2000,30);
        _timer.addEventListener(TimerEvent.TIMER, tickHandler);
    }
 
    private function tickHandler(e:TimerEvent):void {
        var t:Date = new Date();
 
        var h:Number = t.getHours();
        var m:Number = t.getMinutes() + h * 60;
        var s:Number = t.getSeconds() + m * 60;
        var ms:Number = t.getMilliseconds();
 
        _tween.proxy.secAngle = -90 + s * 6 + ms * 0.006;
        _tween.proxy.minAngle = -90 + s * 0.1;
        _tween.proxy.hourAngle = -90 + (s / 120);
    }
    ...
}

At the core of the Clock component is a single timer. When the timer fires, it uses the current date to compute the angle of the hour hand, minute hand, and second hand. The actual motion of the hands is managed via the awesome proxy functionality in Grant Skinner’s GTween library.

All the interesting FXG action takes place in the skin, so let’s check it out:

<?xml version="1.0" encoding="utf-8"?>
<s:Skin
        xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        creationComplete="complete()">
 
    <fx:Metadata>
        [HostComponent("components.Clock")]
    </fx:Metadata>
 
    <fx:Script>
        <![CDATA[
            private function complete():void {
                ...lots of programmatic FXG here...
            }
        ]]>
    </fx:Script>
 
    ...lots of vanilla FXG here...
 
    <s:Path rotation="{hostComponent.minAngle}" ...
    <s:Path rotation="{hostComponent.hourAngle}" ...
    <s:Path rotation="{hostComponent.secAngle}" ...
</s:Skin>

Getting data to the skin is done via the standard binding to hostComponent. There is no need for the more complicated partAdded() and partRemoved() mechanism, because the Clock component is not intended for general use, unlike my previous components: Terrific TabBar, SuperTextInput, and Drawer.

The skin has a big block of programmatic FXG skinning, done in actionscript code inside the complete() handler which is fired by the creationComplete event. It also has a big block of vanilla MXML declarative FXG skinning, which, most importantly, includes the clock hands and the previously mentioned binding to hostComponent.

By its nature, a clock has a lot of identical elements that are positioned in a circle. The obvious attack is to put the repeated elements in a loop, or set of loops, and go the programmatic route to construct the skin. For example, the long thin ticks along the outer ring are constructed with a double loop. Here’s the relevant snippet of code from inside the complete() handler:

for each (var i:int in [0,30,60,90,120,150,180,210,240,270,300,330]) {
    for each (var j:int in [6,12,18,24]) {
        var p:Path = new Path();
        p.data = "M 174,-0.5 L 184,-0.5 184,0.5 174,0.5 Z";
        p.x = 250;
        p.y = 250;
        p.rotation = i + j;
        p.fill = gray;
        this.addElementAt(p, 1);
    }
}

A new Path element is created and its data property is set. Our tick mark is 10px long, but only 1px wide. With each iteration, a tick mark is created and rotated into place. There are two important tricks in this code that are worth pointing out. First, the rotation origin is at (0,0) for each element, so we must construct our path from -0.5 to 0.5 for it to rotate correctly. Second, we must use addElementAt() to place each element into the proper layer of the drawing because the programmatic FXG code runs after all the vanilla (aka non-programmatic) FXG has been drawn.

Conclusion

No one in their right mind would ever build a clock skin like this. To do this the right way, you’d definitely want to use an image or two to construct the skin. The only reason I went the programmatic FXG skinning route was to verify to myself that it could be done. So, yes it can be done, and I enjoyed the trip.

Files

 7.15

Back in the days of Flex 3, if you wanted multiple content areas in your main application, you’d need to arrange some set of containers (Canvas, HBox, VBox) in the app and fill them with content. It was just your basic Flex 3 development process. The danger, of course, is that you are mixing content with presentation, aka bad separation of concerns. Today, with the power of Flex 4 skins, we can avoid this issue by moving the presentation layer into a skin (or set of skins). And thus, we can do a much better job achieving a happy level of separation of concerns.

The Flex 3 Way

To give a concrete example, I’ll build a blog layout (yes, another blog layout) with a header, footer, sidebar, and main content areas. But before we get started, let’s review the old Flex 3 way:

<mx:HBox id="header">
    <mx:Image source="@Embed('assets/logo.png')" />
</mx:HBox>
 
<mx:Canvas id="body" width="800">
    <mx:Text text="main content" width="600" />
 
    <mx:VBox id="sidebar" x="600" width="200">
        <mx:Text text="Sidebar" />
        <mx:Text text="sidebar content" width="100%" />
    </mx:VBox>
</mx:Canvas>
 
<mx:VBox id="footer">
    <mx:Text text="2010 saturnboy" styleName="footer" />
</mx:VBox>

The above code comes from a previous post, Designing in Flex 3, but has been modified to make sense here. You’ve got you basic blog design: a box for the header, footer, and body, where body is subsequently is divided into a main content area and a sidebar.

The 3-in-4 Way, aka The Wrong Way

The unfortunate next step in a Flex developer’s evolution is what I like to call the Flex 3-in-4 way. This is a the way of neanderthals, which is to say, it is an evolutionary dead end. If you ever have the bad luck to see 3-in-4 code, you can be sure you are dealing with a novice Flex 4 developer. In general, the 3-in-4 way consists of making the simple transcription: CanvasGroup, HBoxHGroup, VBoxVGroup. But the most damning tipoff of a 3-in-4 developer is the assertion that one is now a Flex 4 developer and the learning curve wasn’t all that bad. While I do think Flex 4 is more of an evolutionary release than a revolutionary release, it’s different enough. And it is particularly different on the design side of the framework, how it handles skins, layout, etc.

If we just transcribe the above example, we get some classic 3-in-4 code:

<s:HGroup id="header">
    <s:Label text="Multi Content Area Example" styleName="header" />
</s:HGroup>
 
<s:Group id="body" width="800">
    <s:Label text="main content" width="600" />
 
    <s:VGroup x="600" width="200" styleName="sidebarBox">
        <s:Label text="Sidebar" styleName="title" />
        <s:Label text="sidebar content" styleName="sidebar" />
    </s:VGroup>
</s:Group>
 
<s:VGroup id="footer">
    <s:Label text="2010 saturnboy" styleName="footer" />
</s:VGroup>

*Barf*, please not do this. This code has all the same issues as the Flex 3 code in the first example, and moreover it is a slap in the face of The Flex 4 Way and all of its improvements.

The Flex 4 Way

Yes, there is a Flex 4 Way and it looks like this.

First, we rewrite the main app using a custom container. Ignoring the specifics of the custom container for a moment, here is the re-written main app (minus some clutter):

<containers:headerContent>
    <s:Label text="Multi Content Area Example" styleName="header" />
</containers:headerContent>
 
<containers:sidebarContent>
    <s:RichText left="0" right="0" styleName="sidebar">
        <s:content>
            <s:p fontSize="20">Sidebar</s:p>
            <s:p>sidebar content</s:p>
        </s:content>
    </s:RichText>
</containers:sidebarContent>
 
<containers:footerContent>
    <s:Label text="2010 saturnboy" styleName="footer" />
</containers:footerContent>
 
<s:RichText left="0" right="0">
    <s:content>
        <s:p fontSize="30">Content</s:p>
        <s:p>main content</s:p>
    </s:content>
</s:RichText>

As you can see, the main app is now a nice set of semantic buckets, one for each of the content areas. Header stuff goes in the headerContent bucket, footer stuff goes in the footerContent bucket, etc.

Building a Multi Content Area Container

Second, we need to create a custom container with the nice set of semantic buckets used in the above code. This is achieved by following a straightforward formula:

  1. Extend SkinnableContainer – Extend SkinnableContainer or some child class. In our sample app, our custom container extends Application (which extends SkinnableContainer).
  2. Add Buckets – add some content buckets (in the form of xxxContent) as Arrays. These become the MXML tags used to bucket components together. Each content bucket has a public getter, but most importantly a public setter that accepts an incoming Array of IVisualElements and uses the magical mxmlContent property to assign it to the associated SkinPart.
  3. Add SkinParts – add some matching SkinParts (in the form of xxxGroup) as spark Groups. There are used in the custom skin to display the content. Also, I usually set required="false" to make everything optional.
  4. Add partAdded() & partRemoved() – override the new Flex 4 skinning lifecycle methods to wire the incoming content to the outgoing SkinPart.

The custom component code is actually easier to follow then the description. Here is a custom container with only one additional content bucket, sidebarContent, and its matching SkinPart, sidebarGroup:

package containers {
    import spark.components.Group;
    import spark.components.Application;
 
    public class MainApp extends Application {
        [SkinPart(required="false")]
        public var sidebarGroup:Group;
 
        private var _sidebarContent:Array = [];
 
        public function MainApp() {
            super();
        }
 
        [ArrayElementType("mx.core.IVisualElement")]
        public function get sidebarContent():Array {
            return _sidebarContent;
        }
        public function set sidebarContent(value:Array):void {
            _sidebarContent = value;
            if (sidebarGroup) {
                sidebarGroup.mxmlContent = value;
            }
        }
 
        override protected function partAdded(partName:String, instance:Object):void {
            super.partAdded(partName, instance);
 
            if (instance == sidebarGroup) {
                sidebarGroup.mxmlContent = _sidebarContent;
            }
        }
 
        override protected function partRemoved(partName:String, instance:Object):void {
            super.partRemoved(partName, instance);
 
            if (instance == sidebarGroup) {
                sidebarGroup.mxmlContent = null;
            }
        }
    }
}

Following the four steps: we extend Application, have a sidebarContent bucket and its associated sidebarGroup SkinPart, and override partAdded() and partRemoved() to wire everything together.

Skinning a Multi Content Area Container

Skinning in Flex 4 is awesome, and like everyone says, it’s easily one of the best new features in the framework. While I find the skinning process fairly straightforward, I would never call it trivial, mostly due to the depth and flexibility of the skinning system.

We need a custom skin for our custom multi content area component. This is probably the 10% case for skinning, but it’s also the coolest. In my experience, an average Flex 4 app has many Button skins (like 10 or even 20), a few default component skins (skins for List, DropDownList, TextInput, etc.), and maybe only two or three skins for custom components.

The skin itself is nothing special. To display our custom component’s SkinParts, we simply include a Group with the matching id attribute. For example, our skin will include a <s:Group id="sidebarGroup" /> to display the sidebarGroup SkinPart. Just rinse, wash, repeat, to add all of our custom content areas in the container to the skin.

Here is a trivial skin:

<s:Skin ... >
    <fx:Metadata>
        [HostComponent("containers.MainApp")]
    </fx:Metadata> 
 
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
 
    <s:VGroup left="40" right="40" top="40" bottom="40" gap="20">
        <s:Group id="headerGroup" width="100%" />
        <s:Group id="contentGroup" width="100%" />
        <s:Group id="sidebarGroup" width="100%" />
        <s:Group id="footerGroup" width="100%" />
    </s:VGroup>
</s:Skin>

In this trivial skin, we just shove all the content groups (including SkinnableContainer‘s default Group, contentGroup) into a VGroup. Also note, we correctly set HostComponent to our custom container. If you are thinking, "Hey, this skin looks similar to the Flex 3 and 3-in-4 example code, just minus the content" that’s exactly the point.

Lastly, we wire out skin to our custom component via CSS:

containers|MainApp {
    skinClass:ClassReference('skins.TrivialAppSkin');
}

Using skinClass to wire a skin to a component is so 2009. The sample app has its CSS inline, but in any real app I’ll always put this in an external file.

Conclusion

After this, there’s really not much more to say. You can certainly create a more complicated arrangement of the multiple content areas by making a more complicated skin. I’ve done exactly this in the final sample, which includes three different skins and a skin switcher (click 1, 2, or 3 to switch skins).

» view MultiConentArea sample (view source enabled)

Files

 5.10

Photoshop does this annoying thing where purely vertical gradients have some horizontal variation. Yes, it’s usually only plus or minus one bit of color, but it offends! I’ve battled Photoshop for a while on this, but I just can’t seem to get exactly what I want out of it. So to make a perfect gradient, I decided to write some code. The requirements are simple: given a starting color and a set of deltas, output a perfect gradient.

Here are some quick examples:

1
gradient1
2
gradient2
3
gradient3
#000000
4, 1, 0.25
#eeeeff
-2.2, -1, -0.3
#ff0099
-1, 0, 1
 

If we zoom in on example #1, which starts with black (#000000) and has deltas of 4, 1, 0.25, we see the following:

zoomed gradient
 

The diagram shows the first ten rows of the gradient. The delta values are accumulated with each row, and only the whole part of the resulting color value is used (aka I take the floor of each color bit). So in this example, using the fractional delta of 0.25 results in exactly one additional blue bit every four rows. Ahhh, perfect!

The Code

No need to use some fancy new language, I wrote a simple PHP program to handle commandline input and output a perfect PNG gradient. The interesting part is the function that generates and saves the gradient:

function build_image($filename, $w, $h, $color, $delta) {
  $img = imagecreatetruecolor($w, $h);
 
  $c = imagecolorallocate($img, $color[0], $color[1], $color[2]);
  $d = $delta;
 
  for ($y = 0; $y < $h; $y++) {
    imagefilledrectangle($img, 0, $y, $w - 1, $y + 1, $c);
 
    $c = imagecolorallocate($img,
      clamp(floor($color[0] + $d[0])),
      clamp(floor($color[1] + $d[1])),
      clamp(floor($color[2] + $d[2]))
    );
 
    $d = array($d[0] + $delta[0], $d[1] + $delta[1], $d[2] + $delta[2]);
  }
 
  imagepng($img, $filename);
  imagedestroy($img);
}

The code is straight forward. First, create the image via imagecreatetruecolor(). Then, starting with the starting color, draw a one pixel tall rectangle for each row of the image. The next row’s color is computed in each iteration by adding the accumulated delta to the starting color. Finally, output the image as a PNG via imagepng() and free the memory. The complete php source can be downloaded here.

Button Time

Once we have our perfect gradient engine in place, it’s time to make some perfect buttons. To achieve the standard glass button look-and-feel, I typically fuse two gradients together: light on the top, dark on the bottom.

Here are the two halves of a pretty red button, along with their starting color and deltas:

TOP
BOTTOM
top
bottom
#ff8080
-3,-3,-3
#d23c3c
-3,-3,-3
 

And the two commandline invocations of gradient.php to create the gradients:

php gradient.php 100x16 ff8080 -3,-3,-3 top.png
php gradient.php 100x16 d23c3c -3,-3,-3 bottom.png

If I want my buttons to be sexy, rounded corners are a must. My favorite photoshop trick to create multiple rounded buttons is to use a rounded alpha-transparent button with each gradient as a clipping mask. Using a clipping mask is a simple way to guarantee button geometry remains fixed while colors are changed.

Here is the layers pane showing the two gradients fused together and used as a clipping mask for the rounded alpha-transparent button:

clip mask
 

The result is a horizontally stretchable gradient button, that doesn’t look half bad. See for yourself:

button
 

Custom UIButton

The final button asset can be used as desired, but here is a simple Objective-C example since I’ve been in iPhone world lately:

UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(20, 20, 140, 32)];
[btn setBackgroundImage:[[UIImage imageNamed:@"btn-red.png"]
      stretchableImageWithLeftCapWidth:10.0
      topCapHeight:0.0] forState:UIControlStateNormal];
[btn setTitle:@"BUTTON" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btn.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];

Create a new UIButton of type UIButtonTypeCustom and then set the button skin as the backgroundImage. The horizontal stretchability is due to the stretchableImageWithLeftCapWidth and topCapHeight.

Here is a screenshot from the iPhone simulator showing the button in action:

screenshot
 
Files
  • gradient.php – the perfect gradient engine
  • gradient-button.psd – the photoshop source for the red button image, including the rounded alpha-transparent button and fused red gradients
  • btn-red.png – the red button image

© 2014 saturnboy.com