I have a viewstack with childrens which I want to show/hide depending on the state the application is
<?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"
xmlns:eworx="com.eworx.*"
xmlns:view="com.eworx.view.*"
xmlns:components="com.eworx.view.components.*"
skinClass="com.eworx.view.skins.MainAppSkin"
xmlns:layouts="com.eworx.view.layouts.*"
currentState="login"
initialize="init(event)"
creationComplete="complete(event)"
width="100%"
height="100%">
<fx:Style source="assets/css/screen.css" />
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.core.FlexGlobals;
import mx.events.FlexEvent;
import nl.demonsters.debugger.MonsterDebugger;
private var debugger:MonsterDebugger;
[Bindable]
public var apiUrl:String;
[Bindable]
public var customerType:String;
protected function init(event:FlexEvent):void
{
debugger = new MonsterDebugger(this);
}
protected function complete(event:FlexEvent):void
{
var activated:Boolean = FlexGlobals.topLevelApplication.parameters.activated;
var passwordReset:Boolean = FlexGlobals.topLevelApplication.parameters.passwordReset;
var message:String = FlexGlobals.topLevelApplication.parameters.message;
apiUrl = FlexGlobals.topLevelApplication.parameters.apiUrl;
if(activated)
{
Alert.show(message,"Notice");
}
if(passwordReset)
{
Alert.show(message,"Notice");
}
systemManager.addEventListener(MouseEvent.MOUSE_WHEEL,onMouseWheel,true);
}
private function onMouseWheel(e:MouseEvent):void
{
e.delta *= 5;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<eworx:Seven7Context contextView="{this}" />
<s:Fade id="fadeIn" alphaFrom="0" alphaTo="1" duration="300" />
<s:Fade id="fadeOut" alphaFrom="1" alphaTo="0" duration="300" />
<s:Rotate3D id="r3d" angleYFrom="0" angleYTo="360" duration="300" />
</fx:Declarations>
<s:states>
<s:State name="login" />
<s:State name="wholesale" />
<s:State name="retail" />
</s:states>
<view:LoginForm id="loginForm" includeIn="login" horizontalCenter="0" verticalCenter="0" />
<s:Group excludeFrom="login" width="960" horizontalCenter="0">
<s:BitmapImage width="100%" height="42" x="13" y="80" source="#Embed('assets/garnish/bar.png')" />
<mx:Image source="assets/garnish/logo.png" top="23" />
<s:HGroup verticalAlign="middle" x="198" y="47">
<s:TabBar skinClass="MainMenuTabBarSkin" dataProvider="{vs}" buttonMode="true"/>
<mx:LinkButton id="logout" label="Logout" click="{currentState='login'}" />
</s:HGroup>
<s:HGroup top="0" right="0" gap="1" verticalAlign="top">
<components:OfferList />
<components:MarginBuildersTrack />
<components:CartTrack top="0" />
</s:HGroup>
<mx:ViewStack
id="vs"
top="120"
horizontalCenter="0"
width="960"
height="100%"
resizeToContent="true" >
<view:HomePage showEffect="{fadeIn}" hideEffect="{fadeOut}" label="Home" />
<view:ShowroomPage showEffect="{fadeIn}" hideEffect="{fadeOut}" label="Showroom" />
<view:CataloguePage showEffect="{fadeIn}" hideEffect="{fadeOut}" label="Catalogue" />
<!--<view:IncentivesPage showEffect="{fadeIn}" hideEffect="{fadeOut}" label="Incentives" />-->
<view:RetailCustomerProfilePage includeIn="retail" showEffect="{fadeIn}" hideEffect="{fadeOut}" label="My Profile" />
<view:WholesaleCustomerProfilePage includeIn="wholesale" showEffect="{fadeIn}" hideEffect="{fadeOut}" label="My Profile" />
<view:ClientsPage excludeFrom="retail,login" showEffect="{fadeIn}" hideEffect="{fadeOut}" label="My Clients" />
<view:CartPage showEffect="{fadeIn}" hideEffect="{fadeOut}" label="My Cart" />
<view:OrdersPage showEffect="{fadeIn}" hideEffect="{fadeOut}" label="My Orders" />
</mx:ViewStack>
</s:Group>
</s:Application>
AS you can see I inlude the retail customer view in the retail state and the wholesale customer view in the wholesale state. The problem is that when I run my app they don't appear on neither state.
Any ideas?
This is an odd approach to me. The whole purpose of the ViewStack is to only show one item at once. This is a very odd approach.
I see you have a tabbar whose dataProvider is the ViewStack. However, your ViewStack is not created as a bindable property on the component, and you never seem to set up an initial state. So, I theorize that this is happening:
App Loads in default state, which is the empty string
ViewSTack and/or TabBar are initialized without those children
App state changes for some reason
TabBar does not update
CreationPolicy may come into play too, but I'm not sure. You'll have to step through the code to figure out what's going on. I would strongly recommend you consider an alternate approach to this. Possibly creating the tabbar navigator dataProvider manually based on user security settings or the current state.
Related
i try to make some foldable groups, like an accordion component
i create a Base.as class and extends from Group,code like this
package
{
import flash.events.MouseEvent;
import spark.components.Group;
public class Base extends Group
{
public var header:Group;
public var body:Group;
public function Base()
{
super();
}
override protected function initializationComplete():void
{
super.initializationComplete();
if(header)
{
header.addEventListener(MouseEvent.CLICK,changeState);
}
}
protected function changeState(event:MouseEvent):void
{
if(currentState=="fold")
currentState="unfold";
else
currentState="fold";
}
}
}
and i defined two properties,header and body here,but i don't instantiate here,and then i worte a mxml component "FoldUnit.mxml" that extends "Base" and i will instantiate header and body in it,code like this
<?xml version="1.0" encoding="utf-8"?>
<local:Base xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" currentState="fold" clipAndEnableScrolling="true"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:local="*" width="200" >
<local:states>
<s:State name="fold" />
<s:State name="unfold" />
</local:states>
<local:transitions>
<s:Transition toState="fold">
<s:Sequence>
<s:Resize target="{this}" duration="400" />
<s:RemoveAction target="{body}" />
</s:Sequence>
</s:Transition>
<s:Transition toState="unfold">
<s:Resize target="{this}" duration="400" />
</s:Transition>
</local:transitions>
<s:Group id="header" width="100%">
<s:Rect height="40" width="100%">
<s:fill>
<s:SolidColor color="0xff0000" />
</s:fill>
</s:Rect>
</s:Group>
<s:Group id="body" includeIn="unfold" y="40" width="100%">
<s:Rect height="200" width="100%">
<s:fill>
<s:SolidColor color="0x00ff00" />
</s:fill>
</s:Rect>
</s:Group>
</local:Base>
after all,i placed three of FoldUnit in main application to simulate an accordion component.
<?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:Group>
<s:layout>
<s:VerticalLayout variableRowHeight="true" />
</s:layout>
<local:FoldUnit />
<local:FoldUnit />
<local:FoldUnit />
</s:Group>
</s:Application>
everything like fine,however,if i try to click one red header to fold up,that green body just disappear immediately,looks like that RemoveAction tag is useless.
so,as i try to figure out why,i made things simple first,and i combine that function in Base.as into FoldUnit.mxml,then it works fine.
so,i wonder is there a bug or something?
PS:i don't wanna use a skinable component,coz' the size measure process always delayed,it's hard to location the scroll position in scroll bar.
I have the list shown below:
<s:List id="list2" width="100%" height="100%" dataProvider="{ recordingsShown }"
itemRenderer="components.VideoItemRenderer2"
selectedIndex="0" visible="false">
<s:layout>
<s:TileLayout id="tilelayout"
useVirtualLayout="true"
orientation="columns"
columnAlign="justifyUsingWidth" rowAlign="justifyUsingHeight"
requestedColumnCount="3"
requestedRowCount="2"
paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"
verticalGap="10" horizontalGap="10" />
</s:layout>
</s:List>
which displays in tiles a name, a date and a preview image for each one of the videos contained in the arraycollection recordingsShown given as dataprovider.
The problem is when a new video is added,i save the preview pic in a folder and a node describing it in an xml and i put a new item in the arraycollection with
recordingsShown.addItemAt(newRecording,0);
it is added on stage but the preview image of the last added video is not shown!
How can i redraw the whole list in order to show it?
Here is my itemRenderer:
<?xml version="1.0" encoding="utf-8"?>
<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/mx"
width="400" height="300" autoDrawBackground="true">
<fx:Metadata>
[Event(name="playClicked", type="flash.events.Event")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import flash.filters.GlowFilter;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.formatters.DateFormatter;
protected function img_rollOverHandler(evt:MouseEvent):void {
Image(evt.currentTarget).filters = [new GlowFilter(0xf7941d)];
Image(evt.currentTarget).alpha = 0.9;
}
protected function img1_rollOutHandler(evt:MouseEvent):void {
Image(evt.currentTarget).filters = [];
Image(evt.currentTarget).alpha = 1;
}
protected function playClickHandler(event:MouseEvent):void
{
dispatchEvent(new Event("playClicked",true,true));
}
]]>
</fx:Script>
<fx:Declarations>
<s:DateTimeFormatter id="dateTimeFormatter"
dateTimePattern="DD.MM.YYYY HH.NN.SS"/>
</fx:Declarations>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="selected" />
</s:states>
<s:Rect width="100%" height="100%" radiusX="5" radiusY="5">
<s:filters>
<s:DropShadowFilter alpha="0.32" alpha.hovered="0.5" blurX="5" blurY="5" distance="2" />
</s:filters>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0x323232" color.selected="black"/>
<s:GradientEntry color="#7f7f7f" color.selected="0x333333"/>
</s:LinearGradient>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#ffffff" color.hovered="#f7941d" color.selected="#ed7f09" caps="none" weight="2" joints="miter" miterLimit="4"/>
</s:stroke>
</s:Rect>
<s:Label left="10" top="10"
fontStyle="italic"
fontWeight="bold"
color="#f7941d"
text="{dateTimeFormatter.format(data.date)}"/>
<s:Label left="10" top="25"
fontSize="16"
fontWeight="bold"
color="#ffffff"
text="{data.name}"/>
<s:Image id="previewImg" left="10" right="10" bottom="10" top="55" scaleMode="stretch" smooth="true"
source="http://localhost:5080/thumbs/{data.thumb}" />
<!-- source="assets/img.jpg"/> -->
<s:Image source="assets/play.png"
rollOver="img_rollOverHandler(event);"
rollOut="img1_rollOutHandler(event);"
x="136" y="102"
click="playClickHandler(event)"
complete="this.invalidateSize()"/>
</s:ItemRenderer>
I have found that there seems to be a problem with data binding and the Spark Image. Try adding this to the root tag:
dataChange="yourImage.validateNow();
If that doesn't work, set the whole path in dataChange.
I have a problem which involves skinned buttons returning to their default skins after certain actions occur in my application. Below I have included a partial screenshot where you can observe the problem.
The left button is returned to its default skin after it was clicked (the click triggers a state transition). The right button is the default skinned button. Note that my mouse is neither over nor pressing the left button.
The code for the Button Skin is as follows:
<?xml version="1.0" encoding="utf-8"?>
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
import spark.components.Group;
static private const exclusions:Array = ["labelDisplay"];
override public function get colorizeExclusions():Array {return exclusions;}
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:Rect id="fill" left="1" right="1" top="1" bottom="1" radiusX="2">
<s:fill>
<s:LinearGradient rotation="270">
<s:GradientEntry color.down="#545454"
color.over="#444444"
color="#343434"
alpha="0.95"/>
<s:GradientEntry color.down="#767676"
color.over="#666666"
color="#565656"
alpha="0.95"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Rect id="border" left="0" right="0" top="0" bottom="0" width="69" height="20" radiusX="3">
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1" color="#343434" caps="round" joints="round" />
</s:stroke>
</s:Rect>
<s:Label id="labelDisplay"
textAlign="center" verticalAlign="middle" maxDisplayedLines="1" fontSize="12"
left="10" right="10" verticalCenter="0"
color="#FFFFFF" fontFamily="SegoeUI">
</s:Label>
Here's the code for the transition that is causing the problem:
<s:Transition fromState="State0" toState="State1">
<s:Sequence targets="{[contacts_nocontacts, contacts_list, button_contacts, button_add, button_delete, ac_vgroup]}">
<s:Parallel>
<s:Fade target="{contacts_nocontacts}" alphaFrom="1" alphaTo="0" duration="200" />
<s:Fade target="{contacts_list}" alphaFrom="1" alphaTo="0" duration="200" />
<s:Fade target="{button_add}" alphaFrom="1" alphaTo="0" duration="200" />
<s:Fade target="{button_delete}" alphaFrom="1" alphaTo="0" duration="200" />
</s:Parallel>
<s:RemoveAction targets="{[contacts_nocontacts, contacts_list, button_add, button_delete]}" />
<s:AddAction targets="{[button_contacts, ac_vgroup]}" />
<s:Parallel>
<s:Fade target="{button_contacts}" alphaFrom="0" alphaTo="1" duration="300" />
<s:Fade target="{ac_vgroup}" alphaFrom="0" alphaTo="1" duration="300" />
</s:Parallel>
</s:Sequence>
</s:Transition>
It looks like the skin is being set to the spark.skins.spark.DefaultButtonSkin (not to be confused with the normal Button skin - spark.skins.spark.ButtonSkin). This happens when you set emphasized="true" on the Button or that button is being used as a default Button in a Form.
See this thread for an example of how to customize the emphasized skin: http://forums.adobe.com/message/3811868
The problem is that the Skin is reset when focus is lost on a button that is set as Default button. It's standard behaviour, a quick fix can be found beneath (it's the same solution as the one Steven pointed out, but It's easier to have it on this actual page)
s|Button.emphasized {
skinClass: ClassReference("MyNewButtonSkin");
}
Just attach the same button skinClass on the emphasized style property of your button. The best way to do this the quickest is to do it with above CSS. On this way you can target all the buttons at once!
If i want check parent node checkbox means below childerns checkbox will select automatic .
this is my code:
<fx:Script>
<![CDATA[
private function init():void {
httpTree.send();
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id="httpTree" url="Assets/World.xml"
resultFormat="e4x" useProxy="false" />
</fx:Declarations>
<mx:Tree dataProvider="{httpTree.lastResult.department}"
id="treeTree" labelField="#name"
itemRenderer="com.ItemRenderForTree" width="160" height="200" />
itemRenderer file
<fx:Script>
<![CDATA[
protected function checkboxSelectHandler(event:Event):void
{
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
<s:State name="selected" />
</s:states>
<s:HGroup left="0" right="0" top="0" bottom="0" verticalAlign="middle">
<s:Rect id="indentationSpacer" width="{treeListData.indent}" percentHeight="100" alpha="0">
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Rect>
<s:Group id="disclosureGroup">
<s:BitmapImage source="{treeListData.disclosureIcon}" visible="{treeListData.hasChildren}" />
</s:Group>
<s:BitmapImage source="{treeListData.icon}" />
<s:CheckBox change="checkboxSelectHandler(event)" />
<s:Label id="labelField" text="{treeListData.label}" paddingTop="2"/>
</s:HGroup>
any one can help thanks....
Use tree dataDescriptor to access children nodes of clicked parent node. Maybe that could help? Does your three data have a selected property in datamodel?
You're looking for what I've always called a Schrodinger Check Box. Here is a same piece of code, including a working demo and the PNG resources for the checkbox over at adobe.
Schrodinger Check Box
is there a common way to disable a tab of a spark tabbar component in flex 4? with the mx tabnavigator component you can just disable the content corresponding to the tab and the tab is also disabled then. but doing this with the spark tab bar component disables just the content not the tab.
here is my simple example:
<mx:TabNavigator x="122" y="155" width="200" height="200">
<s:NavigatorContent label="Tab 1" width="100%" height="100%">
<s:Label text="Label1"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 2" width="100%" height="100%" enabled="false">
<s:Label text="Label2"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 3" width="100%" height="100%">
</s:NavigatorContent>
</mx:TabNavigator>
<s:TabBar x="368.7" y="100.35" dataProvider="{viewstack1}" />
<mx:ViewStack x="364" y="133" id="viewstack1" width="200" height="200">
<s:NavigatorContent label="Tab 1" width="100%" height="100%">
<s:Label text="Label1"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 2" width="100%" height="100%" enabled="false">
<s:Label text="Label2"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 3" width="100%" height="100%">
<s:Label text="Label3" x="1" y="0"/>
</s:NavigatorContent>
</mx:ViewStack>
many thx,
florian
Addendum:
Literally two minutes after I got back to actually working, I found an "elegant" solution using a skin.
If you apply a custom skinClass to your tab bar you can bind the tab.enabled property just like you'd expect/want.
<fx:Script>
<![CDATA[
[Bindable] private var tab2IsReady:Boolean = false;
private function checkCriteria():void{
tab2IsReady = someOtherThing.isFinished;//Boolean
}
]]>
</fx:Script>
<s:TabBar id="theTabBar"
dataProvider="{viewStack}"
skinClass="skins.CustomTabBarSkin"/>
<mx:ViewStack id="viewStack">
<s:NavigatorContent label="Tab index 0">
<!-- Your first tab's content -->
</s:NavigatorContent>
<s:NavigatorContent label="Tab index 1" enabled="{tab2IsReady}">
<!-- Your second tab's content -->
</s:NavigatorContent>
</mx:ViewStack>
When you type "skinClass" use the auto complete to generate (in FlashBuilder ~4.5+???) the custom skin (named whatever you want).
The code will appear like below (I left out the Script tag).
<?xml version="1.0" encoding="utf-8"?>
<!-- skins/CustomTabBarSkin.mxml
...
Adobe's copyright & doc comments
...
-->
<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">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.TabBar")]
]]>
</fx:Metadata>
<!-- optional Script tag here -->
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<!--- #copy spark.components.SkinnableDataContainer#dataGroup -->
<s:DataGroup id="dataGroup" width="100%" height="100%">
<s:layout>
<s:ButtonBarHorizontalLayout gap="-1"/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
</s:Skin>
<!-- End skins/CustomTabBarSkin.mxml -->
Change:
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
</fx:Component>
To:
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin"
enabled="{data.enabled}" />
</fx:Component>
Then any <s:NavigatorContent/> in the ViewStack with its enabled property set or bound will do exactly what you expect
(be enabled when true, & disabled when false).
One solution to try would be to use mx:VBox components instead of s:NavigatorContent.
From http://blog.flexexamples.com/2007/08/25/enabling-and-disabling-specific-tabs-in-a-tabbar-control/ :
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/25/enabling-and-disabling-specific-tabs-in-a-tabbar-control/ -->
<mx:Application name="TabBar_enabled_test"
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:ApplicationControlBar dock="true">
<mx:CheckBox id="tabBarEnabled"
label="TabBar.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab1Enabled"
label="Tab1.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab2Enabled"
label="Tab2.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab3Enabled"
label="Tab3.enabled"
selected="true"
width="25%" />
</mx:ApplicationControlBar>
<mx:VBox verticalGap="0">
<mx:TabBar id="tabBar"
width="400"
dataProvider="{viewStack}"
enabled="{tabBarEnabled.selected}" />
<mx:ViewStack id="viewStack" width="400" height="100">
<mx:VBox id="tab1"
label="Tab1"
backgroundColor="haloGreen"
enabled="{tab1Enabled.selected}">
<mx:Label text="Label 1" />
</mx:VBox>
<mx:VBox id="tab2"
label="Tab2"
backgroundColor="haloBlue"
enabled="{tab2Enabled.selected}">
<mx:Label text="Label 2" />
</mx:VBox>
<mx:VBox id="tab3"
label="Tab3"
backgroundColor="haloOrange"
enabled="{tab3Enabled.selected}">
<mx:Label text="Label 3" />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:Application>
For those who want an working answer for Flex 4.5 (probably Flex 4 also). I finally figured out a solution. It feels like a hack to me, but Adobe's not answering the call and it's working for me. Here's a simplified example.
<!-- component that has the the TabBar in it... -->
<fx:Script>
<![CDATA[
//imports here
import mx.core.UIComponent;
//imports
private function setTabEnabled(index:int,enabled:Boolean):void{
var theTab:UIComponent = theTabBar.dataGroup.getElementAt(index) as UIComponent;
if(theTab){theTab.enabled = enabled;}
}
]]>
</fx:Script>
<s:TabBar id="theTabBar"
dataProvider="{viewStack}"/>
<mx:ViewStack id="viewStack">
<s:NavigatorContent label="0th Tab">
<!-- ...Content -->
</s:NavigatorContent>
<s:NavigatorContent label="1st Tab">
<!-- ...Content -->
</s:NavigatorContent>
<s:NavigatorContent label="2nd Tab">
<!-- ...Content -->
</s:NavigatorContent>
</mx:ViewStack>
<!-- rest of the component that has the the TabBar in it... -->
Then you just call setTabEnabled(theTabIndex,trueFalse) in an event handler related to whatever decides why the tab is, or isn't, enabled.
I should extend the TabBar to support this, but I've already spent enough time trying to figure it out.
Happy Coding =D