Flex compiler metadata "DefaultProperty" - apache-flex

Given the following:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2009/mxml">
<mx:Panel title="blah">
<mx:Button />
</mx:Panel>
</mx:Application>
Can you tell me where child elements (ex. mx:Button) are assigned in parent elements (ex. mx:Panel) by default by mxmlc. You can set the "DefaultProperty" compiler metadata tag to specify where they are assigned but what does flex do when it is not specified.
For example I've traversed the source of all the flex classes mx:Panel inherits from and DefaultProperty is never mentioned, leading me to wonder what the default value of DefaultProperty.
sorry for any noobishness but i've read the docs inside out.

When writing AS based components, the default property lets you specify a property that you can use as a child-tag. Eg:
<MyComp:TextAreaDefaultProp>Hello</MyComp:TextAreaDefaultProp>
You could as well have used:
<MyComp:TextAreaDefaultProp defaultText="Hello" />
What happens when you don't specify? You don't get a value for that property. Given the following component:
package
{
// as/myComponents/TextAreaDefaultProp.as
import mx.controls.TextArea;
// Define the default property.
[DefaultProperty("defaultText")]
public class TextAreaDefaultProp extends TextArea {
public function TextAreaDefaultProp()
{
super();
}
// Define a setter method to set the text property
// to the value of the default property.
public function set defaultText(value:String):void {
if (value!=null)
text=value;
}
public function get defaultText():String {
return text;
}
}
}
Run this snippet:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="535" height="345"
xmlns:local="*">
<mx:VBox>
<local:TextAreaDefaultProp id="a" defaultText="Hello"/>
<local:TextAreaDefaultProp id="b" > World </local:TextAreaDefaultProp>
<local:TextAreaDefaultProp id="c" />
<mx:TextArea id="z"/>
<mx:Button click="{z.text = a.defaultText
+ ' ' + b.defaultText
+ ' ' + (c.defaultText.length);}" />
</mx:VBox>
</mx:Application>

The compiler actually treats child components of containers as a special case. Take a look at the childDescriptors property of mx.core.Container for some explanation. When you create a Flex component instance in MXML, it isn't instantiated immediately. Instead, a "descriptor" is created, and that is used to instantiate the component at some future time, as determined by the container's creationPolicy property. If you add the -keep-generated-actionscript argument (or the shortened version, -keep) to your compiler arguments, you'll be able to see the AS3 code that the compiler generates from MXML.

Related

Where to put layout code

I need some code to run in a component after all the sizes of its children are known. The component has an absolute layout. I thought my component's measure() function would get called after all it's children's measure() functions had been called, but it seems like since it has an absolute layout, it never even calls measure.
Anyways, it's a Canvas and my override protected function measure():void never runs. What am I doing wrong?
updateDisplayList() is called in UIComponent's commitProperties. I believe this is called after the child sizes are known, and it is where you are supposed to put your layout code.
measure() is not called when you explicitly set a width and height on your components. If you have an absolute layout on your Canvas, but do not set a width and height, measure() will be called.
HTH;
Amy
You don't need to override anything, simply add a listener to the creationComplete of your component. This event is "Dispatched when the component has finished its construction, property processing, measuring, layout, and drawing."
Example where the component inherits from s:Group
<?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:mx="library://ns.adobe.com/flex/mx" width="400" height="300"
creationComplete="group1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function group1_creationCompleteHandler(event:FlexEvent):void
{
//TODO add code here
}
]]>
</fx:Script>
</s:Group>

how to specify height and width of flex alert box in css?

In my Flex 4 app I would like all my alert boxes to be a specific width and height, how do I specify that in the CSS? I want to avoid having to specify the width and height every time I want to show an alert, that's why I'd like to set it in the CSS, but does not look like there's a way to..
Something like this does not work:
mx|Alert
{
height: 100;
width: 300;
}
You can do it Using Style + Code like this
Define Style Properties as
Alert {
height:300;
weight:300;
}
Note: height and weight are not default style of Alert
Using them in Code as
var alert:Alert = Alert.show("Hello World");
alert.explicitHeight = Number(alert.getStyle("height"));
alert.explicitWidth = Number(alert.getStyle("weight"));
Working example of Flex3 is
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="{show()}">
<mx:Style>
Alert {
height:300;
weight:300;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private function show():void
{
var alert:Alert = Alert.show("Hello World");
alert.explicitHeight = Number(alert.getStyle("height"));
alert.explicitWidth = Number(alert.getStyle("weight"));
}
]]>
</mx:Script>
</mx:Application>
Explanation
Since Alert Control by default not support height and weight style, so example used them just for holding user defined values as variable.
In routine to display Alert/Popup on screen Static method show of class Alert is used, which returns the instance/object of created/active Alert/Popup, using this refrence its properties can be manipulated at runtime as done in above example i.e. explicitHeight and explicitWidth.
Hopes that Help
CSS can only be used to set Style properties of components. There are no dimension based style properties for the mx:Alert as you can see here - although there is one to adjust the height of the header named 'headerHeight'.
You could try extending the mx:Alert class and giving it new style properties that would allow you to change the dimensions via CSS. Or you could extend the class and give it default dimensions in its constructor.
You can't do it out of the box, but you could do it by extending your Alert and adding your own logic in the updateDisplayList to check for the style and change the property appropriately.
Generally not recommended however. Just use the properties given to you instead.

Simulate includeInLayout=false in pure Actionscript code

If you know Flex, you probably know what the property "includeInLayout" does. If not, this property make the parent of your component disregard the bounds (like width and height) of your component in render their own bounds.
Description in reference below:
Specifies whether this component is
included in the layout of the parent
container. If true, the object is
included in its parent container's
layout and is sized and positioned by
its parent container as per its layout
rules. If false, the object size and
position are not affected by its
parent container's layout.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/UIComponent.html#includeInLayout
In Flex, for example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="application1_creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler( event:FlexEvent ):void
{
trace( container.width, container.height ); // output: 200 200
}
]]>
</mx:Script>
<mx:Canvas id="container">
<mx:Button label="Test"
width="100"
height="100" />
<mx:Button label="Test2"
width="200"
height="200" />
</mx:Canvas>
</mx:Application>
Now if I set includeInLayout="false" in second button:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="application1_creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler( event:FlexEvent ):void
{
trace( container.width, container.height ); // output: 100 100
}
]]>
</mx:Script>
<mx:Canvas id="container">
<mx:Button label="Test"
width="100"
height="100" />
<mx:Button label="Test2"
width="200"
height="200"
includeInLayout="false" />
</mx:Canvas>
</mx:Application>
I know of all framework architecture involved to implement this property and know than this property is a property from Flex Framework. What I wanna is this behavior in pure actionscript. For example:
import flash.display.Shape;
var myBox:Shape = new Shape();
myBox.graphics.beginFill(0xFF0000);
myBox.graphics.drawRect(0, 0, 100, 100);
myBox.graphics.endFill();
addChild(myBox);
trace(width, height); // output: 100 100
var myAnotherBox:Shape = new Shape();
myAnotherBox.graphics.beginFill(0xFF00FF, .5);
myAnotherBox.graphics.drawRect(0, 0, 200, 200);
myAnotherBox.graphics.endFill();
addChild(myAnotherBox);
trace(width, height); // output: 200 200
Is there some equivalent implementation in pure Actionscript to reproduce this behavior on "myAnotherBox"?
I already tried:
Change transform matrix;
Change transform pixelBounds;
Change scrollRect;
Apply masks;
And no successful.
Cheers...
You are trying to compare to different things.
In the first example, the width and height are from the UIComponent class, which actually represents a "measured" value, as provided by the Flex Framework.
In the second case, the width and height are the actual size of the rendered shape, as provided by the Flash Player.
If you open the UIComponent's implementation, you will notice that it is actually hiding the original meaning of width and height into $width and $height and provide their own implementation to it.
So to answer your question, you cannot achieve what you want working directly with Shapes (pure Flash components)
Every time you draw something in a graphics context, the width and height will update accordingly.
You options:
draw the first one in one graphics, and the second one in another graphics and measure only the first shape
compute the width and height yourself. This is what actually the containers do, and just skip the includeInLayout=false child components.
If you look up in the UIComponent source code, you'll find, that flag includeInLayout is used in invalidation mechanism (exatcly in size invalidation). If includeInLayout of the component is false, then its parent's size and its size is not recalculated.
Invalidation is native flex framework mechanism, which does not exist in pure AS projects.
You need to override width and height in your container:
override public function get width() : Number {
// place your code here
return 100;
}
override public function get height() : Number {
// place your code here
return 100;
}

Prefix for element not bound

I am a newbie in Flex development and using Flash Builder 4 with SDK 4. Now I get the error that "the prefix "fx" for element "fx:Style" is not bound" in line number 4.
I searched for it, and it has sth. to do with namespaces, but I can not solve it by myelf.
I have the file called "UserStory.mxml" in the directory "components" to place it via the main.mxml onto the screen:
<fx:Script>
<![CDATA[
import components.UserStory;
private function init():void {
var userStory1:UserStory = new UserStory();
userStory1.x = 100;
userStory1.y = 100;
userStory1.userStoryText = "test";
this.addChild(userStory1);
}
]]>
</fx:Script>
The file in which the error occurs in line no. 4:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="300" height="150" styleName="userstory">
<fx:Style source="styles/styles.css"/>
<fx:Text x="5" y="5" width="275" height="135" text="{userStoryText}" fontFamily="notes" fontSize="18"/>
<mx:Script>
...
</mx:Script>
</mx:Canvas>
Can someone tell me what's wrong?
As you suspected it is a problem with the namespace. MXML is just XML and in XML you can define namespaces and bind them to a URL. The namespaces are the part before the colon of an XML element and are usually defined on the enclosing element.
If you look at your MXML file you'll see one namespace declaration for the mx namespace:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" ...
The declaration for fx is missing and that's what the compiler complains about. Add the appropriate definition and you should be fine (see this page for more details):
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009" ...
Also, if you are using Flex 4 you should review the file as mx:Canvas is a Flex 3 component and as such not directly usable in Flex 4 apps. Have a look at the API docs of Canvas for the Flex 4 SDK.

How can I skin or change the default cursor in Flex?

How can I skin, or otherwise change, the default cursor (white arrow) displayed in a Flex application?
Yes, this is possible. You'll need to leverage mx.managers.CursorManager.
There's no way to replace the cursor graphic, but you achieve this by adding a new cursor to the manager with a high priority:
CursorManager.setCursor(myCursor, CursorManagerPriority.HIGH);
In the above example, myCursor can be a JPEG, GIF, PNG, or SVG image, a Sprite object, or a SWF file. Additionally, setCursor accepts two additional parameters, xOffset:Number = 0, yOffset:Number = 0, which you can use to, well, offset the image from the actual pointer position, if you need to.
Re: Your comment:
I believe you're correct. There's no way I know of to override a components hover cursor other than some event foo. Keep in mind that it is the most recently added cursor with the highest priority (to the `CursorMangager, of course) that gets displayed.
If you wat to change the cursur you need to check the mouse when it is currently over the TextField sub-object of the Flex TextInput control:
<?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/halo" minWidth="1024" minHeight="768" mouseMove="application1_mouseMoveHandler(event)">
<fx:Script>
<![CDATA[
protected function application1_mouseMoveHandler(event:MouseEvent):void
{
if(event.target is TextField)
{
if(TextField(event.target).type == TextFieldType.INPUT)
{
Mouse.hide();
}
}
else
{
Mouse.show();
}
}
]]>
</fx:Script>
<mx:TextInput width="300" />
</s:Application>
This is simply making it go away, but you could use the opportunity to make the cursor anything you want by replacing Mouse.hide() with the CursorManager methods described in the other comments. I don't really consider this event "trickery" and overriding the PlayerGlobals.swc class is always going to be more difficult than the open Flex SDK stuff.
Have a look at the following example:
http://blog.flexexamples.com/2007/09/10/changing-the-cursor-in-a-flex-application-using-the-cursormanager-class/

Resources