3

Again, a theming question. Because the project I'm working on requires older libraries that extend mx components (such as TitleWindow and TabNavigator), I can't use what I know about Spark skinning directly. However, since the project is being programmed using the default Spark theme (with my modifications on top) rather than the Halo theme, I apparently don't have access to the styles I need (namely backgroundImage and contentBackgroundImage which apparently require Halo to be active). Simply setting Halo to be the theme will break other things, not the least of which my own theme. Plans are in the works to replace the older libraries or at least patch them better to Flex 4, but as of right now, I need a way to style/skin these components without modifying them directly.

It would be ridiculous to be unable to add a background image to a TitleWindow's content area! I've searched the internet high and low all day and tried countless variations of styles, skins, selectors, and combinations thereof with no luck. Doesn't anyone know how to add a background image to the content of a mx TitleWindow while using the Flex 4.1 sdk?!

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Dwight
  • 1,537
  • 2
  • 14
  • 17

2 Answers2

2

Actually, it's not the only way, it's -as you've mentioned- the hardcoded way: sorry about that. You can also skin your TitleWindow component to accept background images.

To create the appropriate skin with all the necessary states, you can copy the base skin: spark.skins.spark.TitleWindowSkin as MyTitleWindowSkin, and add some customization to it:

In the MetaData tag you should enter the name of your custom TitleWindow class:

<fx:Metadata>
    <![CDATA[ 
        [HostComponent("my.package.CustomTitleWindow")]
    ]]>
</fx:Metadata> 

To accept backgroundImage,

  • you should declare a variable: [Bindable] private var backgroundImage:*;
  • override the updateDisplayList(unscaledWidth, unscaledHeight) method, and inside of it initialize this member: backgroundImage = getStyle("backgroundImage");
  • in the <!-- layer 2: background fill --> section, after the solid-color-fill (<s:Rect id="background"...), you should put the following snippet:

    <s:Rect id="backgroundImg" 
        left="1" right="1" 
        top="{topGroup ? topGroup.height : 0}" 
        bottom="{bottomGroup ? bottomGroup.height : 0}">
        <s:fill>
            <!-- BackgroundImage -->
            <s:BitmapFill id="img" source="{backgroundImage}"
                smooth="true" fillMode="scale" />
        </s:fill>
    </s:Rect>
    

Next you need to create a new class (my.package.CustomTitleWindow), that extends TitleWindow, set its skin, and bind the backgroundImage style:

<?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" 
    skinClass="my.package.MyTitleWindowSkin">
    <fx:Metadata>
        [Style(name="backgroundImage", type="*")]
    </fx:Metadata>
    <mx:VBox width="100%" height="100%">
        <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
        <s:Button label="Do something" />
    </mx:VBox>
</s:TitleWindow>

at the end a small test (which worked fine at my side, and i hope it's closer to what you're looking for):

<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
    <my:CustomTitleWindow title="Window without background image"
        width="100%" height="50%" />
    <my:CustomTitleWindow title="Window with background image"
        width="100%" height="50%" backgroundImage="{IMyConstants.MYLOGO}" />
</s:VGroup>

Update

For setting the skin and the background image from a css file, you only need some minor modifications:

Create a CSS file with content:

/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
@namespace my "your.package.*";

my|CustomTitleWindow {
    skin-class: ClassReference("your.package.MyTitleWindowSkin");
}
.twWithBgImage {
    background-image: Embed("icons/logo.png");
}

The test would look like:

<s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
    <my:CustomTitleWindow title="Window without background image"
        width="100%" height="50%" />
    <my:CustomTitleWindow title="Window with background image"
        width="100%" height="50%" styleName="twWithBgImage" />
</s:VGroup>

and you need to remove the skin declaration from the CustomTitleWindow class: skinClass="your.package.MyTitleWindowSkin".

Of course you don't need to apply the skin to the my|CustomTitleWindow class, you could use it just for a css class, this way you surely don't need to modify your existing component.

Update -- without custom component

Forget the CustomTitleWindow class.

skinnedtw.css

/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.twWithBgImage {
    skin-class: ClassReference("your.package.MyTitleWindowSkin");
    background-image: Embed("icons/logo.png");
}

TestApp.mxml

<?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">
    <fx:Style source="assets/skinnedtw.css" />
    <s:VGroup width="100%" height="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
        <s:TitleWindow title="Window without background image"
            width="100%" height="50%">
            <mx:VBox width="100%" height="100%">
                <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
                <s:Button label="Do something" />
            </mx:VBox>
        </s:TitleWindow>
        <s:TitleWindow title="Window with background image"
            width="100%" height="50%" styleName="twWithBgImage">
            <mx:VBox width="100%" height="100%">
                <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
                <s:Button label="Do something" />
            </mx:VBox>
        </s:TitleWindow>
    </s:VGroup>
</s:WindowedApplication>

My output still looks like this: enter image description here

rekaszeru
  • 19,130
  • 7
  • 59
  • 73
  • Is there any way to specify this skin via CSS? I don't have the luxury of creating a derived type because I'm using an already derived type that I am not allowed to change directly (realistically speaking). – Dwight Apr 12 '11 at 13:34
  • yes there is. check my update for the sample. the output was the same as pasted earlier. – rekaszeru Apr 12 '11 at 14:03
  • I don't think you understand. We're using a library that derives the TitleWindow and we *cannot derive our own types*. At least not right now. Is there any PURE CSS+Skin method that will do this? – Dwight Apr 12 '11 at 16:58
  • The last update is a pure css+skin solution. You only have to change the `your.package.CustomTitleWindow` to the TitleWindow class declaration that you are using. – rekaszeru Apr 12 '11 at 17:06
  • i've removed the CustomTitleWindow from the last update, since it was confusing. – rekaszeru Apr 12 '11 at 17:17
  • skinClass only works on spark components: http://stackoverflow.com/questions/2513344/trying-to-add-a-skinclass-to-mxform We tried both changes you suggested and they didn't do anything. Also, for whatever reason, we were also unable to add a rect and hardcode it. Some kind of [object rect] cannot be supported in this container error, for which the internet was no help. – Dwight Apr 12 '11 at 21:06
  • that's right, skins cannot be applied on mx components. really sorry, that i couldn't help. – rekaszeru Apr 12 '11 at 21:31
  • I really appreciate your effort. Your post is a great resource. – Dwight Apr 13 '11 at 13:14
0

if you don't have explicit members in your mx:TitleWindow, than you should consider using a spark BorderContainer as its first child, since you can specify a background image to that.
i'm thinking of something like this:

<?xml version="1.0" encoding="utf-8"?>
<mx: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" layout="absolute" 
    width="400" height="300" backgroundAttachment="">
    <s:BorderContainer backgroundImage="{IMyConstants.MYLOGO}" 
        width="100%" height="100%" backgroundAlpha=".5" />
    <mx:VBox width="100%" height="100%">
        <mx:Text text="{IMyConstants.LOREMIPSUM}" width="100%" height="100%" />
        <mx:Button label="Do something" />
    </mx:VBox>
</mx:TitleWindow>

i hope i understood your problem, and this helps.

rekaszeru
  • 19,130
  • 7
  • 59
  • 73
  • I feared this was the only way. This is hardcoding, not styling. I want to avoid this as much as possible. – Dwight Apr 11 '11 at 13:48