Wednesday, April 18, 2012

KirSizer - Flex AIR Image Sizer app: Part 2

In this tutorial we will style our application - give it a nice, smooth look with some transition effects, as well as add a little bit of functionality to the "actions" combo box.

The first thing we're going to do, is find every ComboBox and NumericStepper object and set their heights to 22. Set the "Width:" and "Height:" labels' widths to 50. Change both mx:TextInputs to s:TextInputs. For the "actionCombo" ComboBox, add a "change" event listener, with a handler function called actionChange().

Then, to each ComboBox object add 4 properties that will be responsible for playing a little animation when the dropdown list opens and closes. The properties are openEasingFunction (set to Linear.easeOut), closeEasingFunction (set to Linear.easeIn), openDuration (set to 300) and close duration (set to 300).

Finally, add hideEffect and showEffect property values to both NavigatorContent objects. Set their values to fadeOut and fadeIn.

<mx:ViewStack id="contentStack" width="100%" height="100%">
<s:NavigatorContent width="100%" height="100%" hideEffect="fadeOut" showEffect="fadeIn">
<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10">
<s:Label>0 files selected</s:Label>
<mx:TileList id="tileList" width="100%" height="100%"/>
<s:Button label="Add folder" width="100%" />
<s:Button label="Add files" width="100%"/>
<s:Button label="Continue" width="100%" click="contentStack.selectedIndex = 1;" />
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent width="100%" height="100%" hideEffect="fadeOut" showEffect="fadeIn">
<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10">
<s:Button label="Return to file selection" width="100%" click="contentStack.selectedIndex = 0;" />

<s:Label>Resize options:</s:Label>

<mx:ComboBox width="100%" id="actionCombo" height="22" dataProvider="{actions}" selectedIndex="0" editable="false" change="actionChange();"
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>
<s:HGroup verticalAlign="middle">
<s:Label width="50">Width:</s:Label>
<s:NumericStepper id="newWidth" height="22" width="150" minimum="1" value="100" maximum="{(widthMeasure.selectedIndex==0)?(100):(4000)}" />
<mx:ComboBox id="widthMeasure" height="22" width="50" dataProvider="{measures}" selectedIndex="0" editable="false" 
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>
</s:HGroup>

<s:HGroup verticalAlign="middle">
<s:Label width="50">Height:</s:Label>
<s:NumericStepper id="newHeight" height="22" width="150" minimum="1" value="100" maximum="{(heightMeasure.selectedIndex==0)?(100):(4000)}"/>
<mx:ComboBox id="heightMeasure" height="22" width="50" dataProvider="{measures}" selectedIndex="0" editable="false" 
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>
</s:HGroup>

<s:Label/>

<s:Label>Output file names:</s:Label>
<s:HGroup verticalAlign="middle">
<s:TextInput width="240" text="%initialName%" />
<s:Button width="35" label="?"/>
</s:HGroup>

<s:Label/>

<s:Label>Output destination:</s:Label>
<s:HGroup verticalAlign="middle">
<s:RadioButton id="oldDestination" label="Same directory" groupName="destinationGroup" selected="true" />
<s:RadioButton id="newDestination" label="Specified directory" groupName="destinationGroup" />
</s:HGroup>
<s:HGroup verticalAlign="middle" width="100%">
<s:TextInput width="100%" enabled="{newDestination.selected}" text="Select destination..." editable="false" />
<s:Button width="80" label="Browse" enabled="{newDestination.selected}"/>
</s:HGroup>

<s:Label/>

<s:Label>Output format:</s:Label>
<mx:ComboBox width="100%" height="22" id="formatCombo" dataProvider="{formats}" selectedIndex="0" editable="false" 
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>

<s:Label/>

<s:Label>Output JPG quality:</s:Label>
<s:HSlider width="100%" minimum="1" maximum="100" value="100" />

<s:Label/>

<s:Button label="Resize" width="100%" />
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>

Go to the Declarations tags and declare 2 mx:Fade objects called fadeIn and fadeOut. This will be the animation for our viewstack transitions. Set the fadeIn's alphaFrom value to 0, alphaTo value to 1, duration to 300; then set fadeOut's alphaFrom to 1, alphaTo to 1, duration to 300.

<mx:Fade id="fadeIn" alphaFrom="0" alphaTo="1" duration="300"/>
<mx:Fade id="fadeOut" alphaFrom="1" alphaTo="0" duration="300"/>

Create fx:Script tags and do 2 things inside: import the Linear effect class, and create a function called actionChange. The actionChange() function contains a switch case statement, which checks what actionCombo's selectedIndex is, and enables or disables width and height components as needed:

<fx:Script>
<![CDATA[
import mx.effects.easing.Linear;

private function actionChange():void{
switch (actionCombo.selectedIndex) {
case 0: case 3:
newWidth.enabled = true;
widthMeasure.enabled = true;
newHeight.enabled = true;
heightMeasure.enabled = true;
break;
case 1:
newWidth.enabled = true;
widthMeasure.enabled = true;
newHeight.enabled = false;
heightMeasure.enabled = false;
break;
case 2:
newWidth.enabled = false;
widthMeasure.enabled = false;
newHeight.enabled = true;
heightMeasure.enabled = true;
break;
}
}
]]>
</fx:Script>

Finally, let's add fx:Style tags to create a CSS for some of the components in our application. I customized the styles to get a nice dark theme for the application:

<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

#contentStack{
backgroundColor: #313131;
}

s|Label{
color: #fcfcfc;
}

s|Button{
chromeColor: #636363;
}

mx|ComboBox{
chromeColor: #636363;
color: #fcfcfc;
contentBackgroundColor: #000000;
rollOverColor: #aaaaaa;
selectionColor: #ffffff;
}
</fx:Style>

Full code:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="300" height="460" 
showStatusBar="false" title="KirSizer">
   
<fx:Declarations>
<mx:ArrayCollection id="measures">
<fx:String>%</fx:String>
<fx:String>px</fx:String>
</mx:ArrayCollection>
<mx:ArrayCollection id="actions">
<fx:String>Fixed width, fixed height</fx:String>
<fx:String>Fixed width, proportional height</fx:String>
<fx:String>Proportional width, fixed height</fx:String>
<fx:String>Proportional sizes to fit specified sizes</fx:String>
</mx:ArrayCollection>
<mx:ArrayCollection id="formats">
<fx:String>Same format as initial file</fx:String>
<fx:String>Convert all to JPG</fx:String>
<fx:String>Convert all to PNG</fx:String>
</mx:ArrayCollection>
<mx:Fade id="fadeIn" alphaFrom="0" alphaTo="1" duration="300"/>
<mx:Fade id="fadeOut" alphaFrom="1" alphaTo="0" duration="300"/>
</fx:Declarations>

<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

#contentStack{
backgroundColor: #313131;
}

s|Label{
color: #fcfcfc;
}

s|Button{
chromeColor: #636363;
}

mx|ComboBox{
chromeColor: #636363;
color: #fcfcfc;
contentBackgroundColor: #000000;
rollOverColor: #aaaaaa;
selectionColor: #ffffff;
}
</fx:Style>

<fx:Script>
<![CDATA[
import mx.effects.easing.Linear;

private function actionChange():void{
switch (actionCombo.selectedIndex) {
case 0: case 3:
newWidth.enabled = true;
widthMeasure.enabled = true;
newHeight.enabled = true;
heightMeasure.enabled = true;
break;
case 1:
newWidth.enabled = true;
widthMeasure.enabled = true;
newHeight.enabled = false;
heightMeasure.enabled = false;
break;
case 2:
newWidth.enabled = false;
widthMeasure.enabled = false;
newHeight.enabled = true;
heightMeasure.enabled = true;
break;
}
}
]]>
</fx:Script>
   
<mx:ViewStack id="contentStack" width="100%" height="100%">
<s:NavigatorContent width="100%" height="100%" hideEffect="fadeOut" showEffect="fadeIn">
<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10">
<s:Label>0 files selected</s:Label>
<mx:TileList id="tileList" width="100%" height="100%"/>
<s:Button label="Add folder" width="100%" />
<s:Button label="Add files" width="100%"/>
<s:Button label="Continue" width="100%" click="contentStack.selectedIndex = 1;" />
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent width="100%" height="100%" hideEffect="fadeOut" showEffect="fadeIn">
<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10">
<s:Button label="Return to file selection" width="100%" click="contentStack.selectedIndex = 0;" />

<s:Label>Resize options:</s:Label>

<mx:ComboBox width="100%" id="actionCombo" height="22" dataProvider="{actions}" selectedIndex="0" editable="false" change="actionChange();"
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>
<s:HGroup verticalAlign="middle">
<s:Label width="50">Width:</s:Label>
<s:NumericStepper id="newWidth" height="22" width="150" minimum="1" value="100" maximum="{(widthMeasure.selectedIndex==0)?(100):(4000)}" />
<mx:ComboBox id="widthMeasure" height="22" width="50" dataProvider="{measures}" selectedIndex="0" editable="false" 
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>
</s:HGroup>

<s:HGroup verticalAlign="middle">
<s:Label width="50">Height:</s:Label>
<s:NumericStepper id="newHeight" height="22" width="150" minimum="1" value="100" maximum="{(heightMeasure.selectedIndex==0)?(100):(4000)}"/>
<mx:ComboBox id="heightMeasure" height="22" width="50" dataProvider="{measures}" selectedIndex="0" editable="false" 
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>
</s:HGroup>

<s:Label/>

<s:Label>Output file names:</s:Label>
<s:HGroup verticalAlign="middle">
<s:TextInput width="240" text="%initialName%" />
<s:Button width="35" label="?"/>
</s:HGroup>

<s:Label/>

<s:Label>Output destination:</s:Label>
<s:HGroup verticalAlign="middle">
<s:RadioButton id="oldDestination" label="Same directory" groupName="destinationGroup" selected="true" />
<s:RadioButton id="newDestination" label="Specified directory" groupName="destinationGroup" />
</s:HGroup>
<s:HGroup verticalAlign="middle" width="100%">
<s:TextInput width="100%" enabled="{newDestination.selected}" text="Select destination..." editable="false" />
<s:Button width="80" label="Browse" enabled="{newDestination.selected}"/>
</s:HGroup>

<s:Label/>

<s:Label>Output format:</s:Label>
<mx:ComboBox width="100%" height="22" id="formatCombo" dataProvider="{formats}" selectedIndex="0" editable="false" 
openEasingFunction="Linear.easeOut" closeEasingFunction="Linear.easeIn" openDuration="300" closeDuration="300"/>

<s:Label/>

<s:Label>Output JPG quality:</s:Label>
<s:HSlider width="100%" minimum="1" maximum="100" value="100" />

<s:Label/>

<s:Button label="Resize" width="100%" />
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>
</s:WindowedApplication>

Thanks for reading!

No comments:

Post a Comment