No matter what I do, I cannot have any effect on Flex MXML elements during initialization.
I want to display a different logo depending on whether a flashVar is true or not.
For some reason the flashvar has no effect on how the elements appear.
Am I missing anything ?
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:components="ru.kutu.grindplayer.views.components.*"
mouseEnabled="false"
implements="ru.kutu.grind.views.api.IMainView"
preinitialize="preinitialize(event)"
>
<s:states>
<s:State name="initializing" />
<s:State name="ready" />
<s:State name="error" />
</s:states>
<s:BorderContainer
id="logoContainer"
left="0" right="0"
top="0" bottom="0"
mouseEnabled="false"
includeIn="initializing"
backgroundColor="0x070707"
borderVisible = "false"
>
<s:Image
id="logoPaid"
verticalCenter="0"
horizontalCenter="0"
source="#Embed('/../assets/skin/dark.png')"
visible="{is_paid}"
/>
<s:Image
id="logoFree"
verticalCenter="0"
horizontalCenter="0"
source="#Embed('/../assets/skin/dark_free.png')"
visible="{!is_paid}"
/>
</s:BorderContainer>
<components:PlayerView
id="playerView"
left="0" right="0"
top="0" bottom="0"
visible="false"
visible.ready="true"
/>
<s:Label
id="errorDisplay"
width="80%"
mouseEnabled="false"
verticalCenter="0"
horizontalCenter="0"
includeIn="error"
itemCreationPolicy="immediate"
/>
<s:transitions>
<s:Transition
fromState="*" toState="*"
autoReverse="true"
interruptionBehavior="stop"
>
<s:Fade
target="{this}"
duration="300"
/>
</s:Transition>
</s:transitions>
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.events.FlexEvent;
[Bindable]
private var is_paid:Boolean;
public function set errorText(value:String):void {
errorDisplay.text = value;
}
public function initializing(is_paid:Boolean):void {
currentState = "initializing";
}
public function ready():void {
currentState = "ready";
}
public function error():void {
currentState = "error";
}
private function preinitialize(event:FlexEvent):void {
is_paid = FlexGlobals.topLevelApplication.parameters.is_paid;
}
]]>
</fx:Script>
I think you parse String into Boolean. Cause params names and values are String, try this instead:
is_paid = FlexGlobals.topLevelApplication.parameters.is_paid == 'true';
Try as I may, I am not able to skin a spark Button, when I place the button within a spark dataGrid. I am constrained to using the halo theme.
I have created the button renderer in a separate mxml file; I have separate buttons outside the dataGrid that show the skin correctly, so I am sure that there is nothing wrong with the skin. The whole point of this is to use the same skin inside the dataGrid as outside
The following code shows the same behavior that I am seeing; in this case the renderer is created in line. It seems like the skinClass is not respected. Or is there another way to do it.
<s:DataGrid id="dg" width="500" dataProvider="{employees2}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="name" headerText="Name">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer>
<s:Button label="Press Me"
top="0" bottom="0" left="0" right="0"
skinClass="MyButtonSkin" />
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
In file MyButtonSkin.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:SparkButtonSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
minWidth="21" minHeight="21"
alpha.disabled="0.5">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
/* Define the skin elements that should not be colorized.
For button, the graphics are colorized but the label is not. */
static private const exclusions:Array = ["labelDisplay"];
/**
* #private
*/
override public function get colorizeExclusions():Array {return exclusions;}
/**
* #private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<!-- states -->
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<!-- layer 2: fill -->
<!--- #private -->
<s:Rect id="fill" left="1" right="1" top="1" bottom="1" radiusX="10">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFAFAFA"
color.over="0xBBBDBD"
color.down="0xAAAAAA"
alpha="0.85" />
<s:GradientEntry color="0x808080"
color.over="0x9FA0A1"
color.down="0x929496"
alpha="0.85" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 8: text -->
<!--- #copy spark.components.supportClasses.ButtonBase#labelDisplay -->
<s:Label id="labelDisplay"
textAlign="center"
maxDisplayedLines="1"
horizontalCenter="0" verticalCenter="1" verticalAlign="middle">
</s:Label>
</s:SparkButtonSkin>
It appears that scaling the button to the size of the grid item does not size the corner radius.
I ended up with a button 200x200 pixels with a corner radius of 6 pixels; it just couldn't be seen. I upped the value to 25 and now I can see it
I have a photo in a Flex project:
<s:Image source="#Embed('images/photo.png')" />
But now I'm wondering if I can make this image as the image below, in Flex (4 / 4.5 / 4.6) (in MXML and/or ActionScript 3):
Is this possible?
Here's a feathering mask tutorial in flash that you should be able to port to Flex.
Yes it is possible, first you need to create a mask layer for the rounder corners and inner shadow using AI or PS
Create a mask in Photoshop or AI. If you're using PS, it must be a vector mask.
Import it to Flash catalyst. If you're using PS, you must chose "Shape Layers > Keep Editable" in the import dialog.
In the layers panel, you'll see a Group with your masked content inside of it. Anything that goes inside that group will be masked.
Add the one image inside the masked group and copy the masked code in code view of Flash catalyst. (FC)
Now create one skin class for the spark image and add the mask code above the imageDisplay (BitmapImage).
MaskedImageSkin.mxml
<?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"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5">
<s:states>
<s:State name="uninitialized" />
<s:State name="loading"/>
<s:State name="ready" />
<s:State name="invalid" />
<s:State name="disabled" />
</s:states>
<fx:Script fb:purpose="styling">
<![CDATA[
/**
* #private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
// Push backgroundColor and backgroundAlpha directly.
// Handle undefined backgroundColor by hiding the background object.
if (isNaN(getStyle("backgroundColor")))
{
background.visible = false;
background.includeInLayout = false;
}
else
{
background.visible = true;
background.includeInLayout = true;
bgFill.color = getStyle("backgroundColor");
bgFill.alpha = getStyle("backgroundAlpha");
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
]]>
</fx:Script>
<!-- host component -->
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Image")]
]]>
</fx:Metadata>
<!--- Defines the appearance of the image background. -->
<s:Rect id="background" left="0" right="0" top="0" bottom="0">
<s:fill>
<!-- #private -->
<s:SolidColor id="bgFill"/>
</s:fill>
</s:Rect>
<s:Group x="0" y="0">
<s:filters>
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="45" distance="10" />
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="90" distance="10"/>
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="-45" distance="10" />
<s:DropShadowFilter color="#FFFFFF" inner="true" blurX="10" blurY="10" quality="5" alpha="0.85" angle="-90" distance="10"/>
</s:filters>
<s:mask>
<s:Group x="0" y="0" width="280" height="180" >
<s:Rect left="0" right="0" top="0" bottom="0" radiusX="10" radiusY="10">
<s:fill>
<s:SolidColor color="#FFFFFF"/>
</s:fill>
</s:Rect>
</s:Group>
</s:mask>
<!--- Primary image display skin part. -->
<s:BitmapImage id="imageDisplay" left="0" top="0" right="0" bottom="0"/>
</s:Group>
<!--- Progress indicator skin part. -->
<s:Range id="progressIndicator" skinClass="spark.skins.spark.ImageLoadingSkin" verticalCenter="0" horizontalCenter="0" includeIn="loading" layoutDirection="ltr" />
<!--- Icon that appears in place of the image when an invalid image is loaded. -->
<s:BitmapImage id="brokenImageIcon" includeIn="invalid" source="#Embed(source='Assets.swf',symbol='__brokenImage')" verticalCenter="0" horizontalCenter="0"/>
</s:Skin>
Apply this skin class for spark image
<s:Image source="#Embed('assets/maskImg.png')" skinClass="MaskedImageSkin" width="200" height="200"/>
The above code is just an example of masking image, create your own mask using rounded rectangle. This will solve your issue.
Happy skinning ...
I try to have a specific window skin according operating system.
See below my skin.
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
xmlns:Layout="skin.Layout.*"
alpha.disabledGroup="0.5"
creationComplete="sparkskin1_creationCompleteHandler(event)">
<fx:Metadata>
[HostComponent("fr.inter.ui.windowSkin.wCustomWindow")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function btResize_mouseDownHandler(event:MouseEvent):void
{
btResize.addEventListener( MouseEvent.MOUSE_UP, btResize_mouseUpHandler );
stage.nativeWindow.startResize();
}
protected function btResize_mouseOutHandler(event:MouseEvent):void
{
btResize.removeEventListener( MouseEvent.MOUSE_OUT, btResize_mouseOutHandler );
}
protected function btResize_mouseUpHandler(event:MouseEvent):void
{
btResize.removeEventListener( MouseEvent.MOUSE_UP, btResize_mouseUpHandler );
}
protected function sparkskin1_creationCompleteHandler(event:FlexEvent):void
{
if (NativeApplication.supportsDockIcon)
{
this.currentState = "supportsDockIcon";//mac
}
else
{
this.currentState = "supportsSystemTray";
}
}
]]>
</fx:Script>
<s:states>
<s:State name="disabledAndInactive" stateGroups="disabledGroup, inactiveGroup" />
<s:State name="maximizedGroup"/>
<s:State name="normal" />
<s:State name="disabled" stateGroups="disabledGroup" />
<s:State name="normalAndInactive" stateGroups="inactiveGroup" />
<s:State name="supportsDockIcon" />
<s:State name="supportsSystemTray"/>
</s:states>
<s:Rect id="backgroundRect"
left="0"
right="0"
top="0"
bottom="0"
alpha="0"
>
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
<s:Group bottom="0" left="0" right="0"
top="0"
>
<!--Fond de la fenetre-->
<s:Rect bottom="0" left="0" right="0"
top="0"
radiusX="8" radiusY="8" >
<s:fill>
<s:SolidColor color="#656565" alpha=".7" />
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#666666" />
</s:stroke>
</s:Rect>
<s:Group height="38" id="moveArea"
left="0" right="0" >
<!--Barre bleu avec filet-->
<s:Rect height="25" left="10" right="10" top="10">
<s:fill>
<s:SolidColor color="#055a90" />
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#666666" />
</s:stroke>
</s:Rect>
<s:BitmapImage id="icon"
left.supportsSystemTray="5" right.supportsDockIcon="5"
verticalCenter="0" />
<s:Label id="titleDisplay"
styleName="swindowTitle"
left.supportsSystemTray="60" left.supportsDockIcon="{this.width/2}"
top="18" verticalAlign="middle" horizontalCenter="0"
/>
<!--Zone de bouton-->
<s:HGroup right.supportsSystemTray="12" left.supportsDockIcon="12" verticalCenter="0">
<s:Button id="btMinimize" buttonMode="true"
skinClass.supportsSystemTray="skin.components.MinimizeButtonSkin"
skinClass.supportsDockIcon="skin.components.MinimizeButtonSkinM"
verticalCenter="0"/>
<s:Button id="btMaximize" buttonMode="true"
skinClass.supportsSystemTray="skin.components.MaximizeButtonSkin"
skinClass.supportsDockIcon="skin.components.MaximizeButtonSkinM"
verticalCenter="0"/>
<s:Button id="closeButton" buttonMode="true"
skinClass.supportsSystemTray="skin.components.CloseButtonSkin"
skinClass.supportsDockIcon="skin.components.CloseButtonSkinM"
verticalCenter="0"/>
</s:HGroup>
</s:Group>
<!--Fond de la zone principale-->
<s:Rect id="background" left="10" top="35" right="10" bottom="10">
<s:fill>
<s:LinearGradient rotation="-90">
<s:GradientEntry color="#edf0f7"/>
<s:GradientEntry color="#fcfbfb" />
</s:LinearGradient>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#666666" />
</s:stroke>
</s:Rect>
<!--Zone dans laquelle les elements vont se positionner-->
<s:Group id="contentGroup" left="15" right="15" top="43" bottom="15" minWidth="0"
minHeight="0" width="100%" height="100%">
</s:Group>
</s:Group>
<s:Button height="15" id="btResize" width="15"
bottom="0" right="0"
skinClass="spark.skins.spark.windowChrome.GripperSkin"
mouseDown="btResize_mouseDownHandler(event)"
buttonMode="true"/>
When windows is loading firt, buttons appear well.
But if window is desactivate and after activate, MacOs and Windows buttons appear.
I don't know how to solve that, could you help me?
Thanks
You're not supposed to set the Skin's currentState directly from within the Skin because the hostComponent should take care of that. When you deactivate and re-activate the Window, the hostComponent will set the Skin state back to one of its original states (e.g. normal) and hence disregards your two custom states.
If you want to set the Skin's state based on certain conditions you should override the getCurrentSkinState() method of the hostComponent. But in this particular case I don't think that would be the right approach, because it would be too complicated.
The easiest solution here I think would be to override the Skin's updateDisplayList() method to position your elements. This is the method that takes care of correctly displaying all the elements in your Skin.
<fx:Script>
<![CDATA[
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (NativeApplication.supportsDockIcon) {
titleDisplay.left = width / 2;
//position other elements for mac
}
else {
titleDisplay.left = 60;
//position other elements for win
}
}
]]>
</fx:Script>
Another - perhaps even better - approach would be to create two separate Skin's (one for Mac, one for Windows) and apply the correct Skin to your Windows. This would rid us of the continous if/else checking for capabilities.
I have a simple doubt. I have made a custom ActionScript mxml component, which is a spark TitleWindow with a text area, which header (titlebar) should display a green background if it finds the word 'success' in its text, or red, if it doesn't.
My problem is that I don't know where to access and modify this property, and the only turnaround I've found is binding the 'chromeColor' of the TitleWindow to depend on a boolean that will change depending on whether I find or not the word 'success'. And this does change the TitleBar background to the color I desire, however, it also changes the scrollbar color, for example, which is a bit nasty. The code for my class is the following:
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow 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="400"
title="Output: "
chromeColor="{success ? ( 0x00ff6b as uint) : ( 0xFF0000 as uint)}"
close="closeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
[Bindable]
public var success:Boolean = false;
public function setText(text:String):void
{
textContainer.text = text;
if(text.indexOf("SUCCESS")!=-1)
{
success=true;
}
}
protected function closeHandler(event:CloseEvent):void
{
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<s:TextArea id="textContainer" x="0" y="0" width="100%" height="100%"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"
borderVisible="false" editable="false" fontFamily="Courier New"/>
</s:TitleWindow>
So, thanks for reading, and hope anyone knows the answer :)
Cheers,
pepillo
I'd solve it with extending standard component and creating custom skin.
My version of component:
package
{
import flash.events.MouseEvent;
import mx.managers.PopUpManager;
import spark.components.TextArea;
import spark.components.TitleWindow;
[SkinState("disabledSuccessful")]
[SkinState("disabledWithControlBarSuccessful")]
[SkinState("inactiveSuccessful")]
[SkinState("inactiveWithControlBarSuccessful")]
[SkinState("normalSuccessful")]
[SkinState("normalWithControlBarSuccessful")]
public class SuccessfulTitleWindow extends TitleWindow
{
public function SuccessfulTitleWindow()
{
title = "Output: ";
}
[SkinPart(required = "false")]
public var textContainer:TextArea;
private var success:Boolean;
private var textChanged:Boolean;
private var textValue:String;
/**
* #inheritDoc
*/
override protected function commitProperties():void
{
super.commitProperties();
if (textChanged && textContainer)
{
textContainer.text = textValue;
textChanged = false;
}
}
/**
* #inheritDoc
*/
override protected function getCurrentSkinState():String
{
var skinState:String = super.getCurrentSkinState();
return success ? skinState + "Successful" : skinState;
}
/**
* #inheritDoc
*/
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == textContainer)
{
textChanged = true;
invalidateProperties();
}
}
public function setText(text:String):void
{
if (text == textValue)
return;
success = text && text.indexOf("SUCCESS") != -1;
invalidateSkinState();
textValue = text;
textChanged = true;
invalidateProperties();
}
/**
* #inheritDoc
*/
override protected function closeButton_clickHandler(event:MouseEvent):void
{
super.closeButton_clickHandler(event);
PopUpManager.removePopUp(this);
}
}
}
The skin (based on standard skin):
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" blendMode="normal" mouseEnabled="false"
minWidth="76" minHeight="76" alpha.disabledGroup="0.5" width="400">
<fx:Metadata>[HostComponent("SuccessfulTitleWindow")]</fx:Metadata>
<fx:Script fb:purpose="styling">
/* Define the skin elements that should not be colorized.
For panel, border and title background are skinned, but the content area and title text are not. */
static private const exclusions:Array = ["background", "titleDisplay", "contentGroup"];
/**
* #private
*/
override public function get colorizeExclusions():Array {return exclusions;}
/**
* #private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
/**
* #private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
if (getStyle("borderVisible") == true)
{
border.visible = true;
background.left = background.top = background.right = background.bottom = 1;
contents.left = contents.top = contents.right = contents.bottom = 1;
}
else
{
border.visible = false;
background.left = background.top = background.right = background.bottom = 0;
contents.left = contents.top = contents.right = contents.bottom = 0;
}
dropShadow.visible = getStyle("dropShadowVisible");
var cr:Number = getStyle("cornerRadius");
var withControls:Boolean =
(currentState == "disabledWithControlBar" ||
currentState == "normalWithControlBar" ||
currentState == "inactiveWithControlBar");
if (cornerRadius != cr)
{
cornerRadius = cr;
dropShadow.tlRadius = cornerRadius;
dropShadow.trRadius = cornerRadius;
dropShadow.blRadius = withControls ? cornerRadius : 0;
dropShadow.brRadius = withControls ? cornerRadius : 0;
setPartCornerRadii(topMaskRect, withControls);
setPartCornerRadii(border, withControls);
setPartCornerRadii(background, withControls);
}
if (bottomMaskRect) setPartCornerRadii(bottomMaskRect, withControls);
borderStroke.color = getStyle("borderColor");
borderStroke.alpha = getStyle("borderAlpha");
backgroundFill.color = getStyle("backgroundColor");
backgroundFill.alpha = getStyle("backgroundAlpha");
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
/**
* #private
*/
private function setPartCornerRadii(target:Rect, includeBottom:Boolean):void
{
target.topLeftRadiusX = cornerRadius;
target.topRightRadiusX = cornerRadius;
target.bottomLeftRadiusX = includeBottom ? cornerRadius : 0;
target.bottomRightRadiusX = includeBottom ? cornerRadius : 0;
}
private var cornerRadius:Number;
</fx:Script>
<s:states>
<s:State name="normal" stateGroups="normalGroup" />
<s:State name="inactive" stateGroups="inactiveGroup" />
<s:State name="disabled" stateGroups="disabledGroup" />
<s:State name="normalWithControlBar" stateGroups="withControls, normalGroup" />
<s:State name="inactiveWithControlBar" stateGroups="withControls, inactiveGroup" />
<s:State name="disabledWithControlBar" stateGroups="withControls, disabledGroup" />
<s:State name="normalSuccessful" stateGroups="successfulGroup, normalGroup" />
<s:State name="inactiveSuccessful" stateGroups="inactiveGroup,successfulGroup" />
<s:State name="disabledSuccessful" stateGroups="successfulGroup,disabledGroup" />
<s:State name="normalWithControlBarSuccessful" stateGroups="withControls,successfulGroup,normalGroup" />
<s:State name="inactiveWithControlBarSuccessful" stateGroups="withControls, inactiveGroup, successfulGroup" />
<s:State name="disabledWithControlBarSuccessful" stateGroups="withControls, successfulGroup, disabledGroup" />
</s:states>
<!--- drop shadow can't be hittable so it stays sibling of other graphics #private-->
<s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20" alpha="0.32"
alpha.inactiveGroup="0.22" distance="11" distance.inactiveGroup="7"
angle="90" color="0x000000" left="0" top="0" right="0" bottom="0"/>
<!--- drop shadow can't be hittable so all other graphics go in this group -->
<s:Group left="0" right="0" top="0" bottom="0">
<!--- top group mask #private-->
<s:Group left="1" top="1" right="1" bottom="1" id="topGroupMask">
<!--- #private-->
<s:Rect id="topMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<!--- bottom group mask #private-->
<s:Group left="1" top="1" right="1" bottom="1" id="bottomGroupMask"
includeIn="withControls">
<!--- #private-->
<s:Rect id="bottomMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<!--- layer 1: border #private -->
<s:Rect id="border" left="0" right="0" top="0" bottom="0" >
<s:stroke>
<!--- Defines the TitleWindowSkin class's border stroke. The default value is 1. -->
<s:SolidColorStroke id="borderStroke" weight="1" />
</s:stroke>
</s:Rect>
<!-- layer 2: background fill -->
<!--- Defines the appearance of the TitleWindowSkin class's background. -->
<s:Rect id="background" left="1" top="1" right="1" bottom="1">
<s:fill>
<!--- Defines the TitleWindowSkin class's background fill. The default color is 0xFFFFFF. -->
<s:SolidColor id="backgroundFill" color="#FFFFFF"/>
</s:fill>
</s:Rect>
<!-- layer 3: contents -->
<!--- Contains the vertical stack of title bar content and control bar. -->
<s:Group left="1" right="1" top="1" bottom="1" id="contents">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<!--- #private -->
<s:Group id="topGroup" mask="{topGroupMask}">
<!--- layer 0: title bar fill #private -->
<s:Rect id="tbFill" left="0" right="0" top="0" bottom="1">
<s:fill>
<s:SolidColor color="0xFF0000" color.successfulGroup="0x00ff6b" alpha.inactiveGroup="0.8" />
</s:fill>
</s:Rect>
<!--- layer 1: title bar highlight #private -->
<s:Rect id="tbHilite" left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xE6E6E6" />
<s:GradientEntry color="0xFFFFFF" alpha="0.22"/>
</s:LinearGradientStroke>
</s:stroke>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" alpha="0.15" />
<s:GradientEntry color="0xFFFFFF" alpha="0.15" ratio="0.44"/>
<s:GradientEntry color="0xFFFFFF" alpha="0" ratio="0.4401"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<!--- layer 2: title bar divider #private -->
<s:Rect id="tbDiv" left="0" right="0" height="1" bottom="0">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.75" />
</s:fill>
</s:Rect>
<!-- layer 3: text -->
<!--- #copy spark.components.Panel#titleDisplay -->
<s:Label id="titleDisplay" maxDisplayedLines="1"
left="9" right="36" top="1" bottom="0" minHeight="30"
verticalAlign="middle" fontWeight="bold" />
<!-- layer 4: moveArea -->
<!--- #copy spark.components.TitleWindow#moveArea -->
<s:Group id="moveArea" left="0" right="0" top="0" bottom="0" />
<!--- #copy spark.components.TitleWindow#closeButton -->
<s:Button id="closeButton" skinClass="spark.skins.spark.TitleWindowCloseButtonSkin"
width="15" height="15" right="7" top="7" />
</s:Group>
<!--
Note: setting the minimum size to 0 here so that changes to the host component's
size will not be thwarted by this skin part's minimum size. This is a compromise,
more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
-->
<!--- #copy spark.components.SkinnableContainer#contentGroup -->
<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0">
<s:TextArea id="textContainer" width="100%" height="100%"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"
borderVisible="false" editable="false" fontFamily="Courier New"/>
</s:Group>
<!--- #private -->
<s:Group id="bottomGroup" minWidth="0" minHeight="0"
includeIn="withControls">
<s:Group left="0" right="0" top="0" bottom="0" mask="{bottomGroupMask}">
<!-- layer 0: control bar divider line -->
<s:Rect left="0" right="0" top="0" height="1" alpha="0.22">
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<!-- layer 1: control bar highlight -->
<s:Rect left="0" right="0" top="1" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xFFFFFF" />
<s:GradientEntry color="0xD8D8D8" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<!-- layer 2: control bar fill -->
<s:Rect left="1" right="1" top="2" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xEDEDED"/>
<s:GradientEntry color="0xCDCDCD"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:Group>
<!--- #copy spark.components.Panel#controlBarGroup -->
<s:Group id="controlBarGroup" left="0" right="0" top="1" bottom="1" minWidth="0" minHeight="0">
<s:layout>
<s:HorizontalLayout paddingLeft="10" paddingRight="10" paddingTop="7" paddingBottom="7" gap="10" />
</s:layout>
</s:Group>
</s:Group>
</s:Group>
</s:Group>
</s:SparkSkin>
And the simple app to test:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
<s:VGroup verticalCenter="0" horizontalCenter="0">
<local:SuccessfulTitleWindow skinClass="SuccessfulTitleWindowSkin" id="window" />
<s:TextInput change="window.setText(event.currentTarget.text)" />
</s:VGroup>
</s:Application>
The Flex 4 Way to do this, would be to create your own custom skin class by copying the code of TitleWindowSkin and to update this to have a green background. You would then tell felx to use your custom skin by adding a skinClass attribute to the TitleWindow tag or by setting the skinClass in a CSS configuration.
If using FlashBuilder, create a new MXML Skin derived from the skin type you want to override (good to use a package named skins). Then create a new ActionScript class and extend the MXML skin.
You will then have full control over the skin, and be able to extend the template if necessary.
In my case I wanted to override the skin of a TitleWindow [spark.skins.spark.TitleWindowSkin] (even on a mobile device). Many of the Dialog items (i.e. titlebar) are not skinnable but hard coded. tbFill is the ID of the TitleBar. I was able to adjust the Skin code to assign ID property names to the title bar gradient and read Style values to set the colors [in the updateDisplayList function].
Then use the name of your custom skin class as the skinClass property of the item you are skinning.
skinClass="skins.defaultSkin"
Overall it's not that difficult to do, using this method. Here is the skin class.
package skins
{
public class defaultSkin extends dlgTitleWindowSkin
{
public function defaultSkin()
{
super();
this.setStyle("backgroundColor","#fff2bd");
this.setStyle("tbFill_GradientStart","#ff5f3b");
this.setStyle("tbFill_GradientEnd","#ff5f3b ");
}
}
}
In the derived MXML Skin:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
...
tbFill_GradientStart.color = getStyle("tbFill_GradientStart");
tbFill_GradientEnd.color = getStyle("tbFill_GradientEnd");
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
...
<!--- layer 0: title bar fill #private -->
<s:Rect id="tbFill" left="0" right="0" top="0" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry id="tbFill_GradientStart" color="0xD2D2D2"
color.inactiveGroup="0xEAEAEA"/>
<s:GradientEntry id="tbFill_GradientEnd" color="0x9A9A9A"
color.inactiveGroup="0xCECECE"/>
</s:LinearGradient>
</s:fill>
</s:Rect>