Advanced Flex 4 Skinning Techniques

Last couple of weeks I had chance to dig into Flex 4 with all its beauty. If I could compare Flex 4 to Flex 3 It could be done with just one word, impossible. Difference is as big as difference between ASP and ASP.NET (sorry, first example I imagined). Both sounds similar but both are completely different. And finally I can compare Flex 4 to .NET (in different scale obviously) as proper developer framework.

Sure, Flex 3 was nice extension on top of the as3 but don’t get me wrong, whole framework seemed to me as one big bunch of classes with lot of functions and fixes (just that as3 extension). I just didn’t feel comfortable using it somehow. It was slow, not scalable, hard to extend and so on.

Flex 4 brings big difference. Suddenly it feels “developish”. It feels stable, extendable, and scalable. That means that when you learn it there is big chance that you won’t have to learn everything from scratch in next release (Flex 3 RIP). Basically it feels right finally. But as every developer (should) know, perfection doesn’t exist. And so Flex 4 has some limitations on some places, which comes naturally from one of its goals “Design in Mind”.

And most affected it is with skinning. Adobe didn’t try to take care just about developers, but designers too. And I must say they done remarkable job till now. But in every Dev-Design workflow no matter of size, type or complexity there is line where these two groups crash like two universes in string theory. And then there is Big Bang. And in Flex 4, that line is Skins. So let’s see where the problem sits, what are the advantages, limitations and possible solutions.

As I was working on one prototype project where I was using skinning architecture I tried to find best way how to implement Skinning with minimal negative impact on either developer or designer.

I normally use UML diagrams as my brain memory tool so basic understanding of UML could help you understand each technique better. I also provide example with each possible solution. I use excellent (and free) StarUML editor.

I use stripped down example of actual project to better understand differences and relationships between components, skins, its pros and cons.

To even better imagination in real world I use always 2 different components with 2 different skins simulating needs for different functionality and different look for each component while still maintaining some shared look and functionality.

Problem Example:

I wanted to create top slide page which I can reuse in multiple instances while leave designer with ability and responsibility fully customize the look (ideally in Catalyst workflow environment)

NOTE: I originally used PureMVC and its mediators to split Design (skin), Structure (component) and Behaviour (mediator) into separate entities, but to leave examples as simple as possible I’ll leave behavioural implementation in actual component so I won’t use PureMVC.

I simplified components and made them look idiotic to better highlight point of each solution. Also UML Diagrams are simplified so they display just parts we interested in.

Goal:

  • All components should be aware of their states synchronized with their skins.
  • Easily updatable skins for designer.
  • Easily updatable and scalable components for developer.
  • Access Component state from each location.

Solution 1: Unique Component + Unique Skin

flex 4 skinning 1

This is very simple and straightforward, but also hardest to maintain. Designer creates component skin in Catalyst, export it to fxpl library. Developer create component and apply skin from fxpl library. And the nice story ends up here. If there is another component required, designer must create design from scratch and save it as another skin. Developer needs to create another component.

To force skin mirror specific skins from its component I use SkinState metadata:

	[SkinState("open")]
	[SkinState("closed")]

Check here great post about this problematic. It helped me better understand some magic behind skins and states in Flex 4. I actually used that solution on my examples as well. Thanks Justin!
I recommend you to read that post so you’ll understand code in examples much better.

Pros:
-total separation between designer and developer
- quick development on small scale project

Cons:
- no flexibility
- no scalability
- maintenance nightmare

Usage:
I personally would use this scenario on wireframe presentations or very, very small designer driven micro pages.

[view example]

[download source code]

Solution 2: Inherited Component + Unique Skin

flex 4 skinning 2

This solution is similar to previous example. However developer now uses base class to add basic functionality and extend it to add additional features. Designer still creates unique skin for each new component.

Pros:
-total separation between designer and developer
- quick development on small scale project
- more scalable for developer

Cons:
- state management between component and skin
- still not enough scalable
- still maintenance nightmare

Usage:
Small scale projects, where designer needs to have full control over design

[view example]

[download source code]

Solution 3: Inherited Component + Base Skin

flex 4 skinning 3

So far we implemented some OOP technique to make our life little bit easier. But it still required designer to create new skin from scratch each time we create new inherited component. So another step could be to move skinning down to base component.

To be able to add additional content on top of skin, you need to add this element into skin:

Everything you put into component will be virtually placed inside this tag. Important here is id=”contentGroup” which Flex 4 uses to identify placeholder.

As you can see, there is one problem with this solution. Once designer created base skin, it cannot be changed. This solution is good for large projects where components vary between each other with just content or look which can be fixed inline or css.

Pros:
-total separation between designer and developer
- quick development on any scale project
- scalable for developer
- low maintenance costs

Cons:
- design is not flexible

Usage:
Medium-Large scale projects, where production and reusability are most important aspect of project.

[view example]

[download source code]

Solution 4: Composited Component + Multiple Skins

flex 4 skinning 4

So we know that inheritance will help us maintaining several components more easily, but it has its costs. Another solution is what GoF advice us in their book. Use composition instead of inheritance. This solution has benefits both designer and developer related. Developer has his Maintainability and on other hand Designer has his separation and flexibility.

You have to base classes. ComponentWrapper and BaseSkin. Those 2 classes are responsible for content repeated across all Components. Then, for each component you have to create 2 new classes FrontComponent and FrontSkin including all unique elements.

One problem with this solution is interaction between wrapper and front component. Component is part of the display list of wrapper instead of its property. To access component from wrapper we can use this function:

FlexSkinning4/src/components/ComponentWrapper.mxml :

private function get frontComponent():SkinnableContainer
{
        return getElementAt(0) as SkinnableContainer;
}

This function will return actual component so we can access its skin and properties. So now you can change both skins like that:

FlexSkinning4/src/components/ComponentWrapper.mxml :

currentState = "open";
frontComponent.currentState = "open";

Another problem we have is communication from FrontComponent to Wrapper. We can use either parent property or use properly events. First Option is not really proper way to do so I done it with simple event. But even with event option you have another 2 options. Dispatch custom event from child component to parent, or to listen general stateChange event from parent. For ease of use I use second option. Here is Code in ComponentWrapper which makes the magic:

frontComponent.addEventListener(StateChangeEvent.CURRENT_STATE_CHANGE,stateChangeHandler);

and:

private function stateChangeHandler(e:StateChangeEvent):void
{
 
	if(currentState!=e.newState)
	{
		currentState = e.newState;
	}
}

This will ensure that if state in FrontComponent will change so will Wrapper.

This will ensure that if state in FrontComponent will change so will Wrapper.

Pros:
-separation between designer and developer
- scalable for developer
- low maintenance costs

Cons:
- wrapper-component interaction
- component logic flexibility

Usage:
Medium-Large scale projects, where you need have flexibility for both design and development.

[view example]

[download source code]

Solution 5: Composited-Inherited Components + Multiple Skins

flex 4 skinning 5

Now imagine scenario where you have background element logic which is repeated on 9 components but on 10th one is little bit different. In our previous solution you could either use same logic over all elements or create new logic from scratch witch each new front component. To overcome this issue I use something I call Composited-Inherited Components. So I use Composition and Inheritance at the same time.

FlexSkinning5/src/components/FrontComponentBase.mxml :

                   protected function skinnablecontainer1_creationCompleteHandler(event:FlexEvent):void
			{
				label.buttonMode = true;
				label.addEventListener(MouseEvent.CLICK,labelOverHandler);
			}
 
			private function labelOverHandler(e:MouseEvent):void
			{
				showMessage();
			}
 
			protected function showMessage():void
			{
				Alert.show("you clicked label from component base");
			}
 
			override protected function getCurrentSkinState():String {
				return currentState;
			}

I use FrontComponentBase as base class for front components. I put repeated logic into base class and if I need to change behaviour I just override its function from front component.

FlexSkinning5/src/components/FrontComponent2.mxml :

override protected function showMessage():void
{
	Alert.show("need to put beers into fridge");
}

Pros:
-separation between designer and developer
- scalable for developer
- low maintenance costs
- flexibility

Cons:
- wrapper-component interaction
- setup time

Usage:
Medium-Enterprise scale projects, where you need have flexibility for design, development and scalable logic.

[view example]

[download source code]

Issues

To be honest, none of the solutions so far looks really clean for me. It doesn’t feel right. So where is the problem?

Problem 1: Skin Inheritance

So far I found 5 ways how to deal with skinning in Flex 4. But those who know OOP very well probably noticed I did not used inheritance feature on skins. Why? Simply, it’s not possible.
Problem with skinning is that there is so much care about designer-developer workflow that Adobe little bit forgot about reality and developers who have to live in it.

So just for fun, imagine designer taking care about reusing one skin and using it as inherited base for extended skin. Yes exactly. It’s eye wateringly, absurdly funny (Sure there are designers who actually understand it but I call those people Artists or Creatives. Not Designers). So I get this point from Adobe and understand that such a way is not possible when designer taking care about design exclusively. But let’s be honest, that’s not true in some (currently in most) cases. Hopefully Catalyst will be able to bring some light into it, but in its current state (no Flash Builder<->Catalyst roundtrips) it’s still little bit of toy. And one example of this reality is one I provided in this article. Imagine now we decide create side page for stuff like basket, registration, settings, video section..etc. Sure designer can design everything separately but that should follow some theme aspects. And don’t tell me that “css can do that” or similar crap. That’s just way back to old scary Flex 3. Css should be used for different things, as support and management of skins not skinning itself. Now imagine that we decide to change background and base behavioural aspects. Result? Nightmare. Imagine time for designer to spend on changing each skin separately and additionally (because Catalyst doesn’t support roundtrips) developer to manually updating each skin. This is just SCARY.

I’m not saying that Skinning should be changed. Instead it should provide developers with choice. Simple project?.. Cool let’s designer do the stuff entirely. Complex enterprise project?.. Let’s collaborate.

I think skin inheritance should be implemented into Catalyst in way easily used and understand by designer. Remember it’s not the graphic designer who should use Catalyst but kind of UI Designer or Devigner/Flashy guy (no offence.. that’s just timeline designer, not flash developer) who could have at least some understanding of problematic. Just look what you can do with wizards in Visual Studio (even my grandma could create nice website with sql server with it).

Problem 2: Skin – Component interaction

This is another thing I thought will be easy but apparently it’s not. One important thing to realize is that component and skin states are completely separate entities. There is possibility to connect states with skin metadata. Useful function in this situation is:

override protected function getCurrentSkinState():String
{
	return currentState;
}

and

This will ensure that skin state will be mirrored always you change state in component.

Problem 3: State Inheritance

I could be wrong but till now I couldn’t find the way how to apply inherited states. Because <s:states> tag is actual property of component it will be override with inherited class state properties.

This could become annoying as for each new component you have to create same new states.

Solutions I would use if Flex 4 would support…

Solution 6: Cross Inherited Components and Skins

flex 4 skinning 6

I think, having such a feature would be great. Flex would take care about merging skins together. So you don’t have to extend skins. You just extend some component with skin with another component with skin. But to be realistic, It looks quite(or very?) complicated to implement. But it would be great to have it.

Solution 7: Component Inheritance + Skin Inheritance

flex 4 skinning 7

This looks more realistic. This would solve most of issues I had to alternate in previous solutions.

Logic implementation:

Another dilemma with skins comes to putting logic behaviour or better from which location should you access component parts included in your logic. In this example you have 3 choices.

logic

  • From wrapper application (This is the same case of mediators in PureMVC)
  • From front component
  • From base component

Answer is, it depends. If you need access unique feature of particular component encapsulate it into extended component.

If you have some repeated features which are logical parts of internal guts of component, put them into base class.

If you need orchestrate several components and change their properties, use wrapper.

Conclusion

As I found, Flex 4 Skinning is far more complex than I thought. There Are many another solutions how to implement skinning.

Instead of overriding getCurrentSkinState() you could, override set currentSkin function and access states just from component. You could also change skin states directly, or you could override state listeners. Writing every possible solution would cover whole book. And so far I can say that skin inheritance would be benefit.

Note: I use Flash Builder 4 Beta 2 with Flex 4 Beta 2 for all examples

 

3 Responses to “Advanced Flex 4 Skinning Techniques”

  1. kenton says:

    I completely agree with your thoughts. I have found a bug in a Spark skin and instead of just extending and correcting the bug I have to completely copy and paste the entire thing. It is terrifying and means that I have to monitor the trunk for updates the skin and if anything is changed I’ll have to go through a process of patching.

    This may be great for designers but is a nightmare for large code bases.

  2. peter says:

    I also completely agree with your thoughts. This skin inheritance issue is a big problem. Having to copy hundreds of lines of spark skin code to a whole new file just to tweak something small is ridiculous.

  3. Emily says:

    I completely agree with your thoughts. I have found a bug in a Spark skin and instead of just extending and correcting the bug I have to completely copy and paste the entire thing. It is terrifying and means that I have to monitor the trunk for updates the skin and if anything is changed I’ll have to go through a process of patching.

    This may be great for designers but is a nightmare for large code bases.