What is the purpose of 'fb:purpose' in a Flex <fx:Script>? - apache-flex

I've now seen it a few times here and there and it's got me curious.
<fx:Script fb:purpose="styling">
//script stuff
</fx:Script>
So far, I have seen no difference with it there and without it. Nor do I get any compiler erros. How does a script with fb:purpse differ from a script without? What are the consequences for not including a fb:purpose and what are the benefits for including a fb:purpose?

From the Flex 4 documentation:
Most Spark skins have a special block at the top of the skin class. This block typically defines style properties that the skin class respects, including the exclusions that the skin uses. The tag includes a special attribute, fb:purpose="styling":
<fx:Script fb:purpose="styling">
This attribute is used by Flash Builder. When you create a copy of a skin class in Flash Builder, you can opt to make the skin styleable. If you choose to make it styleable, Flash Builder includes this section of the skin class. If you choose not to make the skin styleable, Flash Builder excludes this section.

It's part of the flashbuilder namespace, and won't have any effect on compilation.
There's no documentation for it that's publicly available at the moment, but it's usually generated by FlashBuilder itself, or is included in the Flex framework code from Adobe.
It's used to show the purpose (in a tool readable manner) of a script block, in this case, styling.

If you create a new MXML Skin using Flash Builder (File > New > MXML Skin) you can deselect the "Remove ActionScript styling code" checkbox which signifies that Flash Builder should remove the script block that defines fb:purpose="styling".

As Yaba said, it allows you to check or uncheck "Remove ActionScript Styling" when building a new MXML skin by copying another Skin class.

Related

skinning view in flex mobile to add background: is that a bug?

I added a background to my views in flex mobile.
I just realized that if I do not include that line:
<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0"/>
only my image is shown and I cannot show anything else.
The very strange thing is that I used :
new-mxml skin
and host component: spark.components.View
and the wizzard did not add this crucial line (I have found that on samples):
<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0"/>
1) Is that a bug ? or is there another simpler way do that ?
2) to avoid others bugs like this one, is there some good practises to skin other components ? (using catalyst ? using fireworks ?)
Regards
Is that a bug ? or is there another simpler way do that ?
No, that's not a bug. The skin for a View class has "skin part" named contentGroup, and this is the object that the View component uses to display its child components. Without this skin part, your view has no container to hold the child components.
Every component that has a skin defines a set of "skin parts". Some skin parts are required, others are not.
Strangely enough, the contentGroup skin part is not required, though it's pretty useless to exclude it.
To avoid others bugs like this one, is there some good practises to skin other components ?
The best practice is to look at the documentation to see what skin parts a component declares. For example, here is a link to the "skin parts" section of the docs for the View component. On the top right of every page in the docs, there is a "skin parts" link to jump to this section of the page.
When you use the wizard to create an MXML Skin, you have an option to copy the code from one of the existing skins that Flex defines. If you do this, you will get some code that includes all of the skin parts and a bunch of Adobe styling code.
If you do not copy the original skin, you get an empty MXML skin. However, the wizard will create a comment in the the code telling you what the skin parts are, and if they're required or not. Here's the comment you get when creating an empty View skin:
<!-- SkinParts
name=contentGroup, type=spark.components.Group, required=false
-->
You can use other tools like Catalyst, but they're not necessary (I believe Catalyst has been discontinued anyway). Sometimes I start by creating the skin w/Adobe's default code and stripping away what I don't want. Other times there's so much "clutter", I just use a blank skin.

How to use FXG as mx:Button icon

I'm trying to use a FXG image as the icon for a button that also contains a caption. My FXG file is located at resources/SpeakerIcon.fxg and my attempted usage looks like this in my mxml file:
<mx:Button id="audioButton" label="Audio"
....
icon="{resources.SpeakerIcon}"/>
When I try to use this I get "TypeError: Error #1034: Type Coercion failed: cannot convert resources::SpeakerIcon#41fa0e1 to mx.core.IFlexDisplayObject." My research indicates that FXG files should be s:Graphics which do implement IFlexDisplayObject http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/primitives/Graphic.html.
What simple thing am I missing?
The <s:Graphics/> object is different than the <Graphics/> tag in an FXG document.
<s:Graphics/> is the base class for Spark primitive shape components (like <s:Rect/>). These are not as lightweight as their FXG counterparts. As such they do not implement the IFlexDisplayObject interface (as #Flextras has just posted :)
FXG assets can be treated as SpriteVisualElement in your Flex code, which technically means FXG assets implement the IVisualElement interface.
If you can, use the Spark <s:Button/> class instead of mx. I don't think <mx:Button/> works with FXG.
For an FXG you should use a Sprite or [in your case] a SpriteVisualElement. I don't believe either of those classes implement IFlexDisplayObject.
You may consider wrapping your FXG element up in this FXGImage class from my Apache Flex whiteboard. FXGImage extends UIcomponent which is an IFlexDisplayObject.
Here is a direct link to the source code for the class.

Is it possible to create skinnable components in MXML using the Spark component architecture?

There are lots of examples of how to create skinnable components in AS3 using the new Spark component architecture, however I've yet to find any such examples using MXML.
What I'm mainly referring to is defining the skin parts and skin states. It seems as though the SkinPart metadata is supposed to be associated with properties and as such can't be used in MXML, is this correct?
As far as I can tell, this isn't possible, because - as you rightly pointed out, there's no way to assign property-level metadata in MXML.
But declaring skin contracts in MXML seems like it would go against the spirit of the Skinning architecture, which is to separate the view of the component from it's implementation logic.
And, given that in MXML everything declared has a value, it inherently couples the component to a skin.
Ie:
<!-- labelDisplay has a value -->
<s:Label id="labelDisplay" />
vs
[SkinPart]
public var labelDisplay:Label; // labelDisplay == null;
Likewise, most of the component logic itself would end up in a <fx:Script /> block, which would probably be better suited in a seperate class.

MXML without Flex Framework/Components

The Flex compiler can compile "pure AS3" SWF files that don't contain any Flex Component bytecode. So,
Would it be possible to create a custom component framework (used in place of the Flex Framework), that can still be visually laid out using MXML (read: markup), and compiled down to a SWF without any dependencies on the Flex Framework itself?
Yes, it's possible. Your MXML files are essentially just a different way to specify classes. You can see what mxml files boil down to by compiling your project and providing -compiler.keep-generated-actionscript=true to mxmlc.
bar.mxml:
<?xml version="1.0" encoding="utf-8"?>
<flash:Sprite xmlns:flash="flash.display.*">
</flash:Sprite>
After compiling with mxmlc -compiler.keep-generated-actionscript=true bar.mxml, it turns into the following.
generated/bar-generated.as:
package {
import flash.display.Sprite;
// bunch of imports
public class bar extends Sprite {
public function bar() { super(); }
}
}
There are two different compilers: one that is used for compiling ActionScript code to AVM bytecode and another (mxmlc) that compiles MXML files into ActionScript code which is then in turn compiled by the first compiler. If you want to see what AS3 code is generated, pass the "-keep" parameter to the MXML compiler.
In theory it's possible to do what you suggest. My guess is that mxmlc keys heavily into features from the UIComponent class, so you'd probably have to hack on mxmlc a bit so that it didn't puke on non-UIComponent classes. Even still, since things like [Bindable] / data binding make use of Flex framework features (not plain Flash Player / AVM features) you would be rewriting an awful lot of code.

Flex application to component?

I have an application built in Flex Builder 3. It has a fair amount of mxml and as3 code which uses some other custom compenents. I have looked at the documentation on building components which shows how to make a simple mxml or action script component that extends something like a combobox, but I'm lost as to how to take a whole existing and independently functioning Application and turn it into a reusable component.
Basically, I'd just like to create multiple instances of this app inside of another flex project.
Anyone able to provide a little guidance?
The easy thing to do is to swap the Application mxml tag with a VBox tag...thus making it act like a component.
e.g. If this were your application:
//Foo.mxml
<mx:Appliction xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text = "foo" />
</mx:Appliction>
change it to:
//Foo.mxml
<mx:VBox>
<mx:Label text = "foo" />
</mx:VBox>
and then you can do something like this:
//App.mxml
<mx:Appliction
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="your.package.scheme.*"
>
<local:Foo />
</mx:Appliction>
You may have to make some public properties if you need to pass in any data to the component...
If you simply want some "parent" Flex application to embed several instances of this autonomous child application, then you should see Adobe's "Embedding Asset Types" documentation, which describes how to embed one SWF file in another.
From the documentation:
You typically embed a Flex application
when you do not require the embedding
application to interact with the
embedded application. If the embedding
application requires interactivity
with the embedded application, you
might consider implementing it as a
custom component, rather than as a
separate application.
If you do require interaction between the embedded application and the parent application, you can look into the SWFLoader control.

Resources