Thursday, July 2, 2009

A quick update

Updates:

  • The Degrafa Skin project is progressing. I've added a skin for Application, which shows off a few nice features of Degrafa. I'll be blogging about this soon.
  • I've been doing quite a bit of work with BlazeDS recently, and the experience is nowhere near as pleasant as it should be. More to come on this front over the next couple of months.
  • As usual, I've been hacking Degrafa, although not as often as I'd like. I'll be committing the Filters package in the next few days, and I'll blog about it again with more details. I'll also be checking in support for Ant soon as well.

Tuesday, May 19, 2009

A complete skin for Flex applications using Degrafa (part 1)

Overview

I’ve been working with Degrafa for a while now, using it to build new components and skin the old. I’ve fixed a few bugs, and contributed some new features, which will hopefully see light sooner rather than later. There’s a few blog posts and tutorials around the net on skinning various individual components, but nothing really comprehensive.

To address this, I’ll be building a complete Flex skin using Degrafa, one component at a time through my blog. Download the source code from Google code, and I’ll try to get a component a week added until the entire standard Flex 3 component set is thoroughly skinned.

So with that out of the way, let’s begin, with TabNavigator!

TabNavigator

The core of any skin is of course, the CSS file. Here’s a snippet of what we’re interested in:

TabNavigator
{
 border-skin:ClassReference("parade.TabNavigatorSkin");
 padding-top:0px;
 padding-right:0px;
 padding-bottom:0px;
 padding-left:0px;
 tabStyleName:"navigatorTab";
 firstTabStyleName:"navigatorTab";
 lastTabStyleName:"navigatorTab";
 selectedTabTextStyleName:"selectedTabText";
}

Button.navigatorTab
{
 skin:ClassReference("parade.TabSkin");
 paddingTop:1;
 paddingRight:10;
 paddingBottom:1;
 paddingLeft:10;
}

As you can see, we’re referencing two custom skins: TabNavigatorSkin and TabSkin. One to skin the ViewStack.

The TabNavigator skin source code isn’t particularly exciting, so I won’t reproduce it here. The interesting part that will be new for a lot of readers, is the leveraging of Degrafa’s new states support. Here’s the code in question, taken from TabSkin.mxml:

<degrafa:states>
    
    <!-- Hover -->
    <degrafa:State name="overSkin">
        <degrafa:SetProperty target="{mainFill}" name="color" value="#dddddd"/>
    </degrafa:State>

    <!-- Selected -->
    <degrafa:State name="selectedUpSkin">
        <degrafa:SetProperty target="{outlineShape}" name="top" value="0"/>
        <degrafa:SetProperty target="{notch}" name="top" value="1"/>
        <degrafa:SetProperty target="{notch}" name="visible" value="true"/>
        <degrafa:SetProperty target="{notchOutline}" name="top" value="1"/>
        <degrafa:SetProperty target="{notchOutline}" name="visible" value="true"/>
        <degrafa:SetProperty target="{fillShape}" name="top" value="1"/>
        <degrafa:SetProperty target="{fillShape}" name="bottom" value="-2"/>
        <degrafa:SetProperty target="{bling}" name="top" value="1"/>
        <degrafa:SetProperty target="{bling}" name="visible" value="false"/>
        <degrafa:SetProperty target="{mainFill}" name="color" value="#dddddd"/>
    </degrafa:State>
    <degrafa:State name="selectedOverSkin" basedOn="selectedUpSkin"/>
    <degrafa:State name="selectedDownSkin" basedOn="selectedUpSkin"/>
    <degrafa:State name="selectedDisabledSkin" basedOn="selectedUpSkin"/>
    
</degrafa:states>

If this syntax looks familiar, it’s because it should - it’s based on the existing syntax you’re used to seeing to set up states in regular old MXML components.

A key difference you should pay attention to is that in Degrafa the property that identifies the current selected state is not "currentState", as with regular UIComponents. For Degrafa skins, it’s stored in the "name" field. This is because that’s the way the Halo component model is designed, and in 99% of cases it’s Halo components we’re skinning.

The state names you see above are also just part of Halo’s way of doing things. They’re not consistent across different components, but that’s simply how it is. Adobe have no plans on changing the names to be more sensible, because they’re throwing out the whole thing for Spark, the component model and library that will be in Flash Builder / Flex 4.

To see the skin in action, click the image below (view source enabled):

Application Skin example
View the example app

Next week: Checkboxes! Do you have preferences as to which components you’d like to see examples for earlier than others? Email me, [catch me on Twitter], or leave a comment here on my blog.

Wednesday, March 18, 2009

On using "if(foo)" vs "if(foo != null)"

I was going to leave this topic for a planned series of posts detailing (and explaining) my personal coding style, as it differs somewhat to that laid out by Adobe. But, a few people noticed a comment I made about the subject, so I thought I'd rant on the subject here, where I can explain myself.

Adobe's guidelines tell us that to test if foo is not null, we should use something like the following:

if (foo)
    doSomething();

This does work, and I find it makes for nice readable code. My coding style is based around readability and "pretty", so I do this all the time.

However, there are a lot of places where we're forced by ActionScript's limited overloading capabilities to declare method parameters as Object or *. And this is where bugs creep in.

Let's say you have a method like so:

public function doStuf(howMany : Number, usefulObject : MyClass = null) : void
{
    //Do some stuff

    if (usefulObject)
        doOtherStuff(usefulObject);
}

As it is, this will work fine. You have a howMany argument, and an optional usefulObject argument.

Everything is going fine, and one day you decide that you can actually use the doStuff() function on all sorts of different objects, as well as instances of MyClass - but you'd like to keep the semantics of it the same, so the parameter is still optional.

You've just introduced a bug. One that you won't trip up any existing unit tests, too.

If you're lucky you'll find it soon, but probably not. If it's a week or two before you need to pass in an empty string, or the number 0, or false, you'll be left scratching your head wondering why it's not doing what it's supposed to.

This is why I think it's not necessarily a good practice to be recommending to ActionScript beginners.

I still do it, but I'm trying to weed it out. Once I break the habit, it'll definitely cut down on the syntax errors I put in my Java, anyway ;-)

Thursday, February 19, 2009

Using "protected" as a namespace

I'm a big fan of certain aspects of Object-Oriented software development, one being information hiding. Not in a way that makes it hard to extend classes, but in order to keep the public API as small and neat as possible. That means favouring protected over private, but often I want a read-only or write-only property in the public API, while still supporting binding (or any other processing on set). This can be a problem at compile time when you'd like to be able to use both internally, however. Take the following code snippet of real code:

//----------------------------------
// selectedUser
//----------------------------------

private var _selectedUser : User;

[Bindable("selectedUserChanged")]
public function get selectedUser() : User
{
    return _selectedUser;
}

protected function set selectedUser(value : User) : void
{
    if (_selectedUser == value)
        return;

    _selectedUser = value;
    dispatchEvent(new Event("selectedUserChanged"));
}

//----------------------------------
// Selection callback
//----------------------------------

public function selected(item : Object) : void
{
    if (item == null || displayUsers.contains(item))
        selectedUser = User(item);
}

MXMLC will give us "Error 1000: Ambiguous reference to selectedUser" when we try to compile this code. Namespaces to the rescue! Did you know you can use public, package, protected and private just as you would a normal namespace in most cases? The solution to this particular problem then becomes:

public function selected(item : Object) : void
{
    if (item == null || displayUsers.contains(item))
        protected::selectedUser = User(item);
}

You may note that instead of a protected accessor, I could have cooked up a protected setSelectedUser() function. Which is true, but using the namespace prefix allows me to retain the assignment operator, which I find clearer.

Friday, February 13, 2009

A small request...

I have a small request:

I'd like to know what grinds your gears, and what makes you smile about the Flex library, and about whatever other libraries you use on a daily basis to get your work done. If you have time, please post here or to me off-list a quick summary of your thoughts, some bullet points, or even a link to somebody else's blog posting that sums up your ideas. Anything you've got to say, even if it's no more than "PureMVC ftw!", I'd like to hear it.

I have a keen interest in frameworks, and I'm planning on building something that takes the best ideas I can find (and cook up) from these and my experiences maintaining a mostly-closed-source framework at my 9-5. It's for my own apps, I'll be dog-fooding it, but it will be open source. It's going to be a full-stack framework with an optional Java+Warp+BlazeDS component, so if you think you've got some good ideas, or would like to help, please drop me a line.

This is

  • Tales of Flex
  • From Brisbane, Australia
  • Opinions on Flex development
  • Tips and FAQs
  • Shameless self-promotion

I am

  • Twitterer
  • Flexcoder
  • Maroon
  • Designer
  • Java lover
  • That loud-mouthed Aussie yob
  • Blogger
  • Problem solver
  • Contributor
  • Cricket Fan
  • Lousy photographer
  • Great cook

I read



Subscribe via RSS to receive updates!