TabNavigator can't handle disabled children in Flex 4.5 - apache-flex

I've got a problem while migrating my TabNavigator from Flex 3 to Flex 4.5. Stripped to the bare minimum the following code will produce the bug, namely that the second child of the TabNavigator fails to be created properly:
<?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"
>
<fx:Script>
<![CDATA[
protected function over():void
{
trace('over');
}
protected function content_one_init():void
{
content_one.enabled = true;
navigator.selectedIndex = 1;
}
]]>
</fx:Script>
<mx:TabNavigator
id="navigator"
creationPolicy="auto"
width="100%" height="100%"
>
<mx:VBox
id="content_one"
enabled="false"
creationComplete="content_one_init()"
label="One"
mouseOver="over()"
/>
<mx:VBox label="Two">
<mx:Label text="Content Two" />
</mx:VBox>
</mx:TabNavigator>
</s:Application>
What I see, upon launching, is a TabNavigator with its second tab selected but no content instead of the expected "Content Two" label. The navigator.selectedIndex = 1; instruction is there just for comfort, the bug appears also if you select the second tab with the mouse after launching.
Now comes the fun part: if I do any of the following, the second child gets created:
set creationPolicy="all" on content_one (this is expected),
comment content_one.enabled = true,
remove enabled="false" on content_one,
remove mouseOver="over()" from content_one (this one is really really weird, as the handler is never called anyway)
Is this really a Flex bug, or is there something I'm missing? I'm using Flex 4.5.0.20967, and all of this worked well in Flex 3.5.
Thanks.

This has been confirmed as a bug at Adobe's and filed in their bug database

Related

Flex: How to set hand cursor?

I'm trying to set the hand cursor on an HBox. I've tried buttonMode and useHandCursor but have had no luck. This example displays the busy cursor. Can anyone tell me how to make it display the flashPlayer's hand cursor?
<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" xmlns:components="com.dn2k.components.*" >
<fx:Script>
<![CDATA[
private var cursorID:int;
//cursorManager
protected function box_mouseOverHandler(event:MouseEvent):void
{
cursorManager.setBusyCursor()
}
]]>
</fx:Script>
<mx:HBox id="box" useHandCursor="true" buttonMode="true" mouseChildren="false" backgroundColor="0xcc0000" mouseOver="box_mouseOverHandler(event)">
<s:Label text="Hiya sexy..."/>
</mx:HBox>
This code shows it perfectly while mouse is over container:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<mx:HBox backgroundColor="0xcc0000" buttonMode="true" id="box" mouseChildren="false" useHandCursor="true">
<s:Label text="Hiya sexy..." />
</mx:HBox>
</s:Application>
If you want to set hand cursor in Label you must set mouseChildren=”false” and below is the revised code
<mx:HBox backgroundColor="0xcc0000" buttonMode="true" id="box" useHandCursor="true">
<s:Label text="Hiya sexy..." buttonMode="true" mouseChildren="false" useHandCursor="true" />
</mx:HBox>
Hope this works for you.
What Jeff said. Also you can use CursorManager.setCursor(). You'll have to embed a graphic for the cursor though.
You can also use the newer Mouse class which provides a higher frame rate native cursor.
<mx:HBox rollOver="Mouse.cursor = MouseCursor.BUTTON"
backgroundColor="0" backgroundAlpha="0"
rollOut="Mouse.cursor = MouseCursor.AUTO"/>
The background color and background alpha are used to draw out graphics that are used as the hit area. In empty Spark containers there is a mouseEnabledWhereTransparent property that I don't think existed in mx containers. Here is documentation on it:
When true, this property ensures that the entire bounds of the Group
respond to mouse events such as click and roll over. This property
only goes in to effect if mouse, touch, or flash player gesture events
are added to this instance. In addition, it assumes that the calls to
addEventListener()/removeEventListener() are not superfluous.
Having said that it seems that this works without setting the mouseEnabledWhereTransparent property:
<s:Group id="testingHitGroup" left="10" top="10"
rollOver="cursorObject_rollOver(event)" width="100" height="100"/>

RichText doesn't work with bullets

See the simple application created below. I have a RichTextEditor and a RichText component. The idea is to display whatever typed in the RichTextEditor in the RichText component. Everything else (I think) works except for Bullets! The conversion works as if bullets don't exist!
<?xml version="1.0" encoding="utf-8"?>
<s:Application width="100%"
height="100%"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:HorizontalLayout />
</s:layout>
<fx:Script>
<![CDATA[
import flashx.textLayout.conversion.TextConverter;
import mx.events.FlexEvent;
protected function convert_clickHandler(event:MouseEvent):void
{
richText.textFlow = TextConverter.importToFlow(editor.htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT);
}
]]>
</fx:Script>
<mx:RichTextEditor id="editor" />
<s:Button id="convert" click="convert_clickHandler(event)" />
<s:RichText id="richText" />
</s:Application>
Any idea on how to make Bullets work with RichText ? Am I using the correct conversion method ? TextConverter.importToFlow ?
See the image below.
List items are not a supported by TEXT_FIELD_HTML_FORMAT. You would need to create your own editor that supports the added TextFlow functionality. There is an example of one such editor in Tour de' Flex, but it was written prior to list support in TLF 2. I'm not sure if it's been updated, but if not you will need to add in that functionality yourself.
Good luck!

Switch between Flex Tabbed ViewNavigators

I am working on a Flex TabbedViewNavigatorApplication with three tabs (ViewNavigator elements). I would like to switch from one ViewNavigator to another based upon a user action (via ActionScript code).
I know that switching between Views uses pushView and popView, but I'm working with ViewNavigators, and my searching revealed nothing useful.
I'm trying to switch from Tab2 to Tab1 when an event occurs. In this case, Tab2 contains a list, and when the user makes a selection, I want to jump back to Tab1.
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="onAppReady(event)">
<s:ViewNavigator label="Tab1" width="100%" height="100%" firstView="views.TabOneView"/>
<s:ViewNavigator label="Tab2" width="100%" height="100%" firstView="views.TabTwoView"/>
<s:ViewNavigator label="Tab3" width="100%" height="100%" firstView="views.TabThreeView"/>
</s:TabbedViewNavigatorApplication>
Thanks for your help!
I use the following line of ActionScript to switch from one ViewNavigator to another based on a user action:
TabbedViewNavigator(navigator.parentNavigator).selectedIndex = 1;
It worked like a charm and seems simpler than bubbling events.
This class is strangely undocumented. I have not tried this myself, but from searching online, this is what I found which corroborates with what the rest of the network does.
What you need to do is bubble an event to the TabbedViewNavigatorApplication and from there change the selectedIndex property to whichever tab you need to change to. For example:
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="onCreationComplete()">
<fx:Script>
<![CDATA[
private function onCreationComplete():void
{
this.addEventListener('someEvent', someHandler);
}
private function someHandler(e:Event):void
{
this.selectedIndex = 0; // or whatever index you want.
}
]]>
</fx:Script>
<s:ViewNavigator label="Tab1" width="100%" height="100%" firstView="views.TabOneView"/>
<s:ViewNavigator label="Tab2" width="100%" height="100%" firstView="views.TabTwoView"/>
<s:ViewNavigator label="Tab3" width="100%" height="100%" firstView="views.TabThreeView"/>
</s:TabbedViewNavigatorApplication>
You just need to dispatch a bubbling event from within your children. You could event create a custom event that holds data about which tab to switch to.

spark List with ItemRenderer click function not working

I am having an issue with my ItemRenderer, which I am using for a spark List. My code is the following:
I have this list:
<s:List
id="productSetList"
dataProvider="{ model.productSets }"
change="model.selectSet( productSetList )"
height="100%" width="100%"
borderVisible="false"
itemRenderer="SideBarItemRenderer" top="20" left="15">
</s:List>
and my itemRenderer is:
<s:ItemRenderer
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
width="160" height="175" autoDrawBackground="false" buttonMode="true" useHandCursor="true"
click="click(event)" cacheAsBitmap="true"
>
<fx:Script>
<![CDATA[
import com.png.vm.model.vos.ProductSet;
protected function click(event:MouseEvent):void
{
trace('arthur');
}
]]>
</fx:Script>
<s:BitmapImage source="{ProductSet(data).image}" width="160" height="175"/>
</s:ItemRenderer>
The thing is, if I scroll the list, and click on an item, it does not trace 'arthur' ! Why is this so ? I must trace that all the time that someone clicks in the list!
EDIT:
If I remove change="model.selectSet( productSetList )" in the list, it works!! but I cannot remove that, some suggestions ? How can I switch that to another function?
Trace only works when you are debugging/using the debugging version of Flash Player. Make sure you are using that. If you want a pop-up message use Alert.show("message")
For more information about trace() check out:
http://livedocs.adobe.com/flex/3/html/help.html?content=logging_08.html
And Alert.show(): http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001965.html
If you are running debug player. Try originating the click event from an embedded <s:Group> this way whatever you add in here beyond the bitmap will still trigger the click event.
Something like:
<s:Group width="100%" height="100%" click="click(event)" >
<s:BitmapImage source="{ProductSet(data).image}" width="160" height="175"/>
</s:Group>
I've definitely had click events work for me inside of ItemRenderers before
My apologies, I have finally solved it. The problem was that inside the function,model.selectSet, I was calling List.change; I was messing the list up! My function was as follows:
public function selectSet(list:List):void {
list.layout.verticalScrollPosition=100;
// another stuffs
}
So, I just removed the line : list.layout.verticalScrollPosition=100; and now it`s working fine.
Thanks for all the help!

Flex 4 dynamically resize parent container to contain children

Is there an easy way to make a parent container (eg Group) resize when it's children resize?
Below is a little example app. When I put the 200x200 'food' in the 'stomach' the stomach & it's containing 100x100 'body' should resize to contain the food.
Any ideas?
(from this gist http://gist.github.com/301292)
<?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"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler(event:FlexEvent):void {
}
protected function eatFoodTrigger_clickHandler(event:MouseEvent):void {
var food:Border = new Border();
food.setStyle('backgroundColor', 0x15DCA9);
food.width = 200;
food.height = 200;
stomach.addElement(food);
}
]]>
</fx:Script>
<s:Group verticalCenter="0" horizontalCenter="0">
<s:layout>
<s:VerticalLayout horizontalAlign="center" />
</s:layout>
<s:Label fontSize="24" text="The 100x100 pink/brown body has a stomach inside it.
Press eat and the stomach gets 200x200 'food' added to it.
I want the body and the stomach to expand to fit the food." width="200">
</s:Label>
<s:Border id="body"
backgroundColor="0x333333"
minWidth="100"
minHeight="100"
borderColor="0xFF4466"
borderWeight="5">
<s:Group id="stomach">
</s:Group>
</s:Border>
<s:Button id="eatFoodTrigger" click="eatFoodTrigger_clickHandler(event)" label="eat" />
</s:Group>
</s:Application>
Ok so it was a bug in the flex 4 sdk, and it's been fixed. Awesome.
From: http://forums.adobe.com/thread/575252
Your example works for me in a recent
build. Perhaps it was a bug in an old
build. Try one of the new nightly
builds:
http://opensource.adobe.com/wiki/display/flexsdk/DownloadFlex4
-Ryan
Obviously, this is a bit too late, but you could have overriden the addElementAt-method and added some functionality for resizing there. Below, you can see how addElementAdd() should/could be overridden.
//This would be placed in a custom component that extends Group. Your stomach would be this component.
override public function addElementAt(element:IVisualElement, index:int):IVisualElement
{
super.addElementAt(element, index);
ChangeWatcher.watch(element, "width", function():void{ resizeHandler(element) });
ChangeWatcher.watch(element, "height", function():void{ resizeHandler(element) });
}
private function resizeHandler(el:IVisualElement):void
{
var element:DisplayObject = el as DisplayObject;
//Rest of the resizing code.
}
I know this worked for flex3 and Canvas, so it should also work with flex4 and Group.

Resources