Wizards & Skinning

Back when I was first looking at Flex, I knocked up a little prototype for work to show some people a possible solution to a problem they were having. They need to produce custom catalogs of products for clients that differ in the elements they require and the format of the file produced. Some may want XML, some fixed length fields, others delimited text (, | etc).

I wrote a wizard in Flex that would take you through the process of specifying a file and then use a Java method via BlazeDS to create the file (the Java code just constructed a demo file from the field data you provided for the prototype). In the end, it turned out that getting all the source data for the elements was the real sticking point so it never went any further.

I hadn’t done anything with it since but I started thinking about skinning apps (as a developer, I’m a terrible designer) and figured this wouldn’t be a bad app to try it on. If you go to Scale nine and check out the gallery, you’ll see a number of themes you can download for free. If you can’t find one you like, there should be enough there to show you how to modify one that’s close or write your own.

I downloaded the “Undefined” skin and dumped it all in my wizard project. The skin came with a main mxml file so it was pretty obvious to see how to use it in my own files.  All I had to do was use an mx:Style tag to import the css and specify the styleName property for my components.

I went from a screen that looked like this:

old wizard screen

to one that looked like this:

new wizard screen

While you might not like the look of either of them, you’ve got to admit, it’s pretty nice to be able to change the look of your app so easily.

The app itself makes use of states to change the layout of the screen and walk the user through the steps they have to take.  START is the first state and requests the customer id the catalog is for. There’s no back button in this state as we’ve got nothing to go back to. The next state is the one shown above, PICK_FIELDS. This displays the available fields in the left list from an ArrayCollection (fromAC) defined in the app and the right list is bound to another ArrayCollection (toAC). Drag/drop is enabled to allow the user to specifiy the fields they need and the order they want them in. The next state is SPEC_FIELDS, this contains text fields for a document header and footer (in the case of XML files) and a datagrid which has columns for the field name ( taken from toAC), max length, pad character, pre string and post string. This allows the user to specify the format of each of the elements they have selected. The results are stored in another ArrayCollection (fieldAC). The final state is GENFILE which in this case just displays some debug and removes the buttons but for a final version would display some messaging about the file created.

It’s worth noting also how the states use mx:SetEventHandler to change the behavior of the back and next buttons in the various states. Hopefully it’s fairly obvious what’s going on with that explanation and the source provided below and maybe it’ll provide you with some ideas for your own “wizard” style apps.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" borderColor="#B7BABC" themeColor="#9999CC" currentState="START">
<mx:Style source="/css/skinPreview.css/"/>
<mx:Script>
<![CDATA[

import mx.controls.DataGrid;
import mx.collections.ArrayCollection;

[Bindable]
public var toAC:ArrayCollection = new ArrayCollection();

[Bindable]
public var fromAC:ArrayCollection = new ArrayCollection([“Product Id”, “Price”, “Description”, “Long Description”, “UOM”, “ECO”, “Minority”]);

[Bindable]
public var fieldAC:ArrayCollection=new ArrayCollection();

private function next():void
{
if (currentState==”SPEC_FIELDS”)
{
currentState=”GENFILE”;
}else
{
currentState=(currentState==”START”) ? currentState=”PICK_FIELDS” : currentState=”SPEC_FIELDS”;
}
}

private function back():void
{
currentState=(currentState==”SPEC_FIELDS”) ? currentState=”PICK_FIELDS” : currentState=”START”;
}

private function drawDetails(event:Event):void
{
next();
var toArray:Array=toAC.toArray();
for(var i:String in toArray)
{
var field:FieldData=new FieldData();
field.name=toArray[i];
fieldAC.addItem(field);
}
}

private function wipeDetails(event:Event):void
{
fieldAC.removeAll();
back();
}

private function createFile(event:Event):void
{
next();
ro.createFile(custText.text,docHead.text,fieldAC.toArray(),docFoot.text);
}

]]>
</mx:Script>

<mx:RemoteObject id=”ro” destination=”cif-creator”/>

<mx:states>
<mx:State name=”START”>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:HBox id=”custInput”>
<mx:Label id=”custLabel” text=”Customer Id” styleName=”myText”/>
<mx:TextInput id=”custText” />
</mx:HBox>
</mx:AddChild>

<mx:RemoveChild target=”{backBtn}” />

</mx:State>

<mx:State name=”PICK_FIELDS”>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:HDividedBox id=”divBox” horizontalAlign=”center” horizontalGap=”10″ verticalAlign=”top” label=”Field Chooser” borderStyle=”inset” width=”100%”>
<mx:List id=”fromList” dataProvider=”{fromAC}” allowMultipleSelection=”true”
dragEnabled=”true” dropEnabled=”true”
dragMoveEnabled=”true” styleName=”myText” width=”50%” height=”100%” fontSize=”12″ backgroundColor=”#E2E2E2″/>
<mx:List id=”toList” dataProvider=”{toAC}” allowMultipleSelection=”true”
dragEnabled=”true” dropEnabled=”true”
dragMoveEnabled=”true” styleName=”myText” width=”50%” height=”100%” fontSize=”12″ backgroundColor=”#E2E2E2″/>
</mx:HDividedBox>
</mx:AddChild>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:Label id=”pickHelp” text=”Drag the fields you need from the left column over to the right. You can also re-order by dragging if you need to” styleName=”myText” fontSize=”10″ textAlign=”center”/>
</mx:AddChild>

<mx:SetEventHandler target=”{nextBtn}” name=”click” handlerFunction=”drawDetails”/>
</mx:State>

<mx:State name=”SPEC_FIELDS”>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:HBox id=”headerInput”>
<mx:Label id=”headLabel” text=”Document Header” styleName=”myText” />
<mx:TextInput id=”docHead”/>
</mx:HBox>
</mx:AddChild>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:DataGrid id=”fieldDG” dataProvider=”{fieldAC}” editable=”true”>
<mx:columns>
<mx:DataGridColumn headerText=”Field Name” dataField=”name” editable=”false” backgroundColor=”#E2E2E2″ />
<mx:DataGridColumn headerText=”Max Length” dataField=”maxLength” editable=”true”/>
<mx:DataGridColumn headerText=”Pad Char” dataField=”padChar” editable=”true”/>
<mx:DataGridColumn headerText=”Pre String” dataField=”preString” editable=”true”/>
<mx:DataGridColumn headerText=”Post String” dataField=”postString” editable=”true”/>
</mx:columns>
</mx:DataGrid>
</mx:AddChild>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:HBox id=”footerInput”>
<mx:Label id=”footLabel” text=”Document Footer” styleName=”myText” />
<mx:TextInput id=”docFoot”/>
</mx:HBox>
</mx:AddChild>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:Label id=”specHelp” text=”Only enter data for fields you require. A Max Length of 0 means no limit will be applied” styleName=”myText” fontSize=”10″ textAlign=”center”/>
</mx:AddChild>

<mx:SetEventHandler target=”{backBtn}” name=”click” handlerFunction=”wipeDetails”/>

<mx:SetEventHandler target=”{nextBtn}” name=”click” handlerFunction=”createFile”/>
</mx:State>

<mx:State name=”GENFILE”>

<mx:AddChild relativeTo=”{changeBox}”>
<mx:Label id=”debug” text=”{docHead.text}” textAlign=”center”/>
</mx:AddChild>

<mx:RemoveChild target=”{btnBox}” />
</mx:State>
</mx:states>

<mx:Panel id=”mainPanel” width=”60%” height=”60%” backgroundColor=”#B9B9B9″ backgroundAlpha=”0.51″ alpha=”1.0″ color=”#000000″ layout=”vertical” cornerRadius=”20″ title=”CIF File Creator” borderColor=”#E2E2E2″ themeColor=”#4B4B4B” >

<mx:VBox id=”changeBox” width=”100%” height=”70%” horizontalAlign=”center” verticalAlign=”middle”/>

<mx:HBox id= “btnBox” width=”100%” verticalAlign=”bottom” horizontalAlign=”right” paddingRight=”10″>

<mx:Button id=”backBtn” label=”&lt;Back” click=”back()” styleName=”buttonOfficial”/>

<mx:Button id=”nextBtn” label=”Next&gt;” click=”next()” styleName=”buttonOfficial”/>

</mx:HBox>

</mx:Panel>

</mx:Application>

Advertisements
Posted in Flex. Tags: , . 2 Comments »