When using TabNavigator how to align content of dynamically added tab - actionscript-3

Given a simple example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import com.example.Tab;
private function addSecondTab(event:Event):void {
tabs.addChild(new Tab("Second"));
}
]]>
</mx:Script>
<mx:TabNavigator id="tabs" width="100%" height="100%">
<mx:VBox horizontalAlign="center" verticalAlign="middle" label="#1">
<mx:Label text="test"/>
</mx:VBox>
</mx:TabNavigator>
<mx:Button label="Add Second Tab" click="addSecondTab(event)" />
</mx:Application>
package com.example {
import mx.containers.VBox;
import mx.controls.Label;
import mx.events.FlexEvent;
public class Tab extends VBox {
public function Tab(name:String) {
label = name;
setStyle("horizontal-align", "center");
setStyle("vertical-align", "middle");
}
override protected function createChildren():void {
super.createChildren();
var box:VBox = new VBox();
box.setStyle("border-style", "solid");
box.setStyle("border-thickness", 1);
box.setStyle("border-color", 0xFF0000);
var l1:Label = new Label();
l1.text = "Hello!";
box.addChild(l1);
var l2:Label = new Label();
l2.setStyle("fontWeight", "bold");
l2.text = "This is a line of text...";
box.addChild(l2);
addChild(box);
}
}
}
Why aren't styles (border and alignment) being applied inside the second tab?

Flex only supports hyphenated style names in CSS. So in MXML or Actionscript statements you should use the camel case versions of the style names:
horizontalAlign, verticalAlign, borderStyle, etc.
You can read more about it in Adobe's documentation, in particular this section on CSS selector names.

Related

Main application can't capturing custom event Flex

I have a problem when despatching an custom event from my "ItemRendered" to "Main application",the function "avatarSelectedHandler()" is not called when I click in the "CheckBox" (ItemRendered) located in the "DataGrid", I followed the official doc adobe but unfortunately I have not led to a solution.
below my code :
Try.mxml(Main application)
<?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" creationComplete="initApps()">
<fx:Script>
<![CDATA[
import entity.Avatar;
import events.AvatarSelected;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable]
private var listAvatar:ArrayCollection=new ArrayCollection();
public function initApps():void{
getAvatar();
avatarColumn.addEventListener(AvatarSelected.SELECTED_AVATAR,avatarSelectedHandler);
//avatarGrid.addEventListener(AvatarSelected.SELECTED_AVATAR,avatarSelectedHandler);
if(avatarColumn.hasEventListener(AvatarSelected.SELECTED_AVATAR))
Alert.show("EventListener OK ");
}
public function avatarSelectedHandler(event:AvatarSelected):void
{
Alert.show("L'evenement est bien traité sur main");
}
public function getAvatar():void{
var date:Date=new Date();
var avatar1:Avatar=new Avatar();
avatar1.idAvatar=4562;
avatar1.pseudo="X";
var avatar2:Avatar=new Avatar();
avatar2.idAvatar=659;
avatar2.pseudo="Y";
listAvatar.addItem(avatar1);
listAvatar.addItem(avatar2);
}
]]>
</fx:Script>
<s:DataGrid x="158" y="177" width="649" height="194" fontFamily="Times New Roman" id="avatarGrid"
fontSize="15" requestedRowCount="4" textAlign="center" dataProvider="{listAvatar}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="isAvatar" headerText="Id" ></s:GridColumn>
<s:GridColumn dataField="pseudo" headerText="Pseudo"></s:GridColumn>
<s:GridColumn headerText="Selectionner" width="100" itemRenderer="rendered.CheckRendered" id="avatarColumn"></s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:Application>
My ItemRendered "CheckRendered.mxml"
<?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer 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="50" height="27" clipAndEnableScrolling="true">
<fx:Metadata>
[Event(name="avatarSelected", type="events.AvatarSelected")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import entity.Avatar;
import events.AvatarSelected;
import mx.controls.Alert;
protected function cBox_clickHandler(event:MouseEvent):void
{
var eventAvatar:AvatarSelected=new AvatarSelected("avatarSelected",Avatar (data));
dispatchEvent(eventAvatar);
}
]]>
</fx:Script>
<s:CheckBox id="cBox" horizontalCenter="0" click="cBox_clickHandler(event)"/>
</s:GridItemRenderer>
My custom event "AvatarSelected.as"
package events
{
import entity.Avatar;
import flash.events.Event;
import mx.states.OverrideBase;
public class AvatarSelected extends Event
{
public static const SELECTED_AVATAR:String = "avatarSelected";
public var avatar:Avatar;
public function AvatarSelected(type:String, avatar:Avatar)
{
super(type);
this.avatar =avatar;
}
}
}
My VO "Avatar.as"
package entity
{
//[Bindable]
//[RemoteClass(alias="entity.Avatar")]
[Bindable]
public class Avatar
{
public var idAvatar:Number;
public var pseudo:String;
}
}
I opted for another way to capture the event, I created a class SkinDataGrid that extends GridColumn to accept the event as an argument, but it does not work yet!
DataGrid on the Main Application:
<s:DataGrid x="171" y="333" width="649" height="194" fontFamily="Times New Roman" id="avatarGridII"
fontSize="15" requestedRowCount="4" textAlign="center" dataProvider="{listAvatar}">
<s:columns>
<s:ArrayList>
<skin:SkinDataGrid dataField="isAvatar" headerText="Id" ></skin:SkinDataGrid>
<skin:SkinDataGrid dataField="pseudo" headerText="Pseudo"></skin:SkinDataGrid>
<skin:SkinDataGrid headerText="Selectionner" width="100" itemRenderer="rendered.CheckRendered" id="avatarColumnII" avatarSelected="avatarSelectedHandler(event)"></skin:SkinDataGrid>
</s:ArrayList>
</s:columns>
</s:DataGrid>
SkinDataGrid.as
package skin
{
import spark.components.DataGrid;
import spark.components.gridClasses.GridColumn;
[Event(name="avatarSelected", type="events.AvatarSelected")]
public class SkinDataGrid extends GridColumn
{
public function SkinDataGrid()
{
super();
}
}
}
any idea ?
Thank you in advance.
You don't specify what kind of problem do you have (type of error), but from looking at the code I find suspicious, that function avatarSelectedHandler has as argument of MouseEvent type, when you assign it as handler of AvatarSelected type.
You also can try to dispatch this event with bubbling enabled (by default it's set to false in the Event class constructor).
In your case, the AvatarSelected constructor can be changed to smth like that:
public function AvatarSelected(type:String, avatar:Avatar, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.avatar =avatar;
}
And event creating would be like this (attention on the third parameter in the AvatarSelected()):
var eventAvatar:AvatarSelected = new AvatarSelected("avatarSelected", Avatar (data), true);

Flex 4 component on top of TitleWindow

I have Flex s:Group with some ui elements and I want it to be always (!) on top of any component inside my app, including s:TitleWindow (dialog).
How can I achieve it with Flex 4?
Thanks in advance!
You should use the mx.managers.PopUpManager class. It provides a simple interface to handle displaying content above any other.
You can write your own interface that encapsulates the PopUpManager interface to give you a chance to bring all your "always-on-top" components on top again, even when you add another popup that should appear behind.
Simple example:
public final class AlwaysOnTopPopUpManager {
private static var alwaysOnTopDisplayObjects:Array;
public static function addAlwaysOnTopObject(displayObject:IFlexDisplayObject):void
{
alwaysOnTopDisplayObjects = alwaysOnTopDisplayObjects || [];
if (alwaysOnTopDisplayObjects.indexOf(displayObject) == -1)
{
alwaysOnTopDisplayObjects.push(displayObject);
arrange();
}
}
public static function removeAlwaysOnTopObject(displayObject:IFlexDisplayObject):void
{
if (alwaysOnTopDisplayObjects)
{
var index:int = alwaysOnTopDisplayObjects.indexOf(displayObject);
if (index != -1)
{
alwaysOnTopDisplayObjects.splice(index, 1);
}
}
}
// uses the same interface as mx.managers.PopUpManager
public static function addPopUp(window:IFlexDisplayObject, parent:DisplayObject, modal:Boolean = false, childList:String = null, moduleFactory:IFlexModuleFactory = null):void
{
mx.managers.PopUpManager.addPopUp(window, parent, modal, childList, moduleFactory);
arrange();
}
private static function arrange():void
{
for each (var popup:IFlexDisplayObject in alwaysOnTopDisplayObjects)
{
mx.managers.PopUpManager.bringToFront(popup);
}
}
The class holds a list of objects to appear above any other content. Each time an object is added to that list or to the popups the arrange() method is called and bring all your registered objects to front again.
Add you top component in systemManager.rawChildren after application creationComplete event. See down:
<?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"
creationComplete="application_creationCompleteHandler(event)"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
import mx.managers.PopUpManager;
protected function application_creationCompleteHandler(event:FlexEvent):void
{
panel.width = width;
panel.height = 300;
systemManager.rawChildren.addChild(panel);
}
protected function addPopup():void
{
PopUpManager.addPopUp(titleWin, this, true);
PopUpManager.centerPopUp(titleWin);
}
protected function button_clickHandler(event:MouseEvent):void
{
addPopup();
}
protected function titleWin_closeHandler(evt:CloseEvent):void
{
PopUpManager.removePopUp(evt.currentTarget as UIComponent);
}
]]>
</fx:Script>
<fx:Declarations>
<s:Panel id="panel" backgroundColor="0x00ff00" alpha="0.9" title="Panel">
<s:layout>
<s:VerticalLayout paddingLeft="50" horizontalAlign="left" verticalAlign="middle" />
</s:layout>
<s:Button id="btn" width="200" height="100" label="create popup"
click="button_clickHandler(event)" />
</s:Panel>
<s:TitleWindow id="titleWin"
title="Spark TitleWindow"
close="titleWin_closeHandler(event);"
width="300">
<s:layout>
<s:VerticalLayout paddingLeft="10" paddingRight="10"
paddingTop="10" paddingBottom="10" />
</s:layout>
<s:Label text="Popup window"
fontSize="24"
width="100%"/>
</s:TitleWindow>
</fx:Declarations>
</s:Application>
If all your elements are in the same MXML file, you simply have to put your s:Group element at the bottom of the file as the last element of it.
If your views are wired more dynamically, then you can force its index with something like this:
var topIndex:int = myParentView.numChildren - 1;
myParentView.setChildIndex(myGroupElement, topIndex);
Where myGroupElement if the reference to your s:Group or its ID.
myGroupElement must already be a child of myParentView when this code is executed.
If your s:Group element is only displayed occasionally, you might be interested in Popups.

Create Custom Dialog Box using dispatch events,states and titlewindow in flex/AS3.0

Since a month Iam working on creating a custom dialog box, having parameters like message,state and modal(true/false)
Eg:
showAlert("Hi, how are you doing","Goodmorning", true);
I have learned how to dispatch event. but unable to dispatch the alertevent/popupManager using States.
Below is the code, I am struggling with.
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function onclick(event:MouseEvent):void
{
this.dispatchEvent("Hi, How are you?", "Morning", true);
}
public function dispatchEvent(arg1:String, arg2:String, arg3:Boolean):void
{
var str:*=null;
str.message = arg1;
str.stateName = arg2;
str.modal = arg3;
this.dispatchEvent(new ShowAlert(ShowAlert.SHOW, true));
}
]]>
</mx:Script>
<mx:Button id="click" click="onclick(event)"/>
</mx:Application>
ShowAlert.as
package
{
import flash.events.*;
public class ShowAlert extends Event
{
public var _stateName:String;
public var _closable:Boolean;
public var _message:String;
public var _isModal:Boolean;
public static const SHOW:String="show";
public function flash.events.(arg1:String, arg2:Boolean=false, arg3:Boolean=false)
{
super(arg1, arg2, arg3);
trace("arg1: "+arg1+"\t arg2: "+arg2+"\t arg3: "+arg3);
}
public function set message(arg1:String):void
{
this._message = arg1;
}
public function get message():String
{
return _message;
}
public function get modal():Boolean
{
return _isModal;
}
public function get stateName():String
{
return _stateName;
}
public function set stateName(arg1:String):void
{
this._stateName = arg1;
}
public function set modal(arg1:Boolean):void
{
this._isModal = arg1;
}
public override function clone():flash.events.Event
{
return new ShowAlert(type);
}
}
}
I was unable to write the custom titlewindow using states, so I dint post that.
Please let me know, how to make this happen.
Below is the Sample code, specifying my problem
main.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public var info:IModuleInfo;
public var loadalert:DisplayObject;
import mx.modules.ModuleManager;
import mx.modules.IModuleInfo;
import mx.events.ModuleEvent;
public function init():void
{
Alert.show("This is forst alert.");
}
public function Loadalerrt():void
{
trace("loadalertmodule");
info = ModuleManager.getModule("../bin-debug/alerrtmod.swf");
info.addEventListener(ModuleEvent.READY, modEventHandler);
info.load();
}
public function modEventHandler(event:ModuleEvent):void
{
trace("modeventHandler");
loadalert=info.factory.create() as DisplayObject;
can1.addChild(loadalert);
}
]]>
</mx:Script>
<mx:Button label="Alert in Application" id="b1" click="init()" x="29" y="21"/>
<mx:Button label="Load Module" id="b2" click="Loadalerrt();" x="10" y="92"/>
<mx:Canvas id="can1" x="409" y="57" backgroundColor="cyan"/>
</mx:Application>
alerttmod.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public function alertshow():void
{
Alert.show("This is second alert, You Can see it covers whole application, What I want is its scope should be limited to this specific module, not to whole application ");
}
]]>
</mx:Script>
<mx:Button label="Alert in Module" id="b1" click="alertshow()" x="163" y="100"/>
</mx:Module>
Now I see your problem. I think it is not possible to restrict the modal area of the Alert. I can suggest you to fake the modal behaviour by desabling the modules elements while your dialog is being shown.
May be it can help you...
Here are two components to demonstrate it:
//your module with another Alert
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.managers.PopUpManager;
public function alertshow():void
{
Alert.show("This is second alert...");
}
public function alertshow2():void
{
var customAlert:CustomAlert = new CustomAlert();
customAlert.addEventListener("CLOSED", onCustomAlertClosed);
this.enabled = false;
PopUpManager.addPopUp(customAlert, this, false);
PopUpManager.centerPopUp(customAlert);
}
private function onCustomAlertClosed(evt:Event):void
{
this.enabled = true;
}
]]>
</mx:Script>
<mx:Button label="Alert in Module" id="b1" click="alertshow()" x="163" y="100"/>
<mx:Button label="CustomAlert in Module" id="b2" click="alertshow2()" x="163" y="150"/>
<mx:Canvas width="100%" height="100%" backgroundColor="0xbbbbbb" alpha="0.8" visible="{!this.enabled}"/>
</mx:Module>
//simple CustomAlert as a Panel
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="300" height="200">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
protected function button1_clickHandler(event:MouseEvent):void
{
PopUpManager.removePopUp(this);
this.dispatchEvent(new Event("CLOSED"));
}
]]>
</mx:Script>
<mx:Button x="112" y="128" label="Close" click="button1_clickHandler(event)"/>
</mx:Panel>

finding last character shown on a flex spark label

Among all the options of the spark label, there is none that tells me the last character shown when the text is truncated, is there any way to accomplish this?
For spark Label you can capture the textLines property after updateDisplayList drew the control.
package frm.ria.signoff.views.components
{
import flash.text.engine.TextLine;
import spark.components.Label;
import mx.core.mx_internal;
public class LastShownCharLabel extends Label
{
[Bindable]
public var lastChar:String;
protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
if(mx_internal::textLines.length>0)
{
var charsInfirstLine:int = TextLine(mx_internal::textLines[0]).rawTextLength;
if(text) lastChar = text.charAt(charsInfirstLine-1);
}
}
}
}
here is the mxml file for that. please execute the following code.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function onClick():void
{
lbl.text = StringUtil.trim(lbl.text);
output.text = lbl.text.charAt(lbl.text.length -1);
}
]]>
</mx:Script>
<mx:VBox>
<mx:Label id="lbl" text="Sagar "/>
<mx:Button click="{onClick();}" label="Click" />
<mx:TextInput id="output" />
</mx:VBox>
</mx:Application>

ActionScript Item Renderer in DataGrid

I am using this example from blog.flexexamples.com.
I have a datagrid and trying to dynamically add button to one of datagrid column. But I want this Button as an ItemRenderer to be written in ActionScript and not MXML.
How can I do that ?
Thanks
I think this is what you need.
ActionButtonItemRenderer.as :
package
{
import flash.events.MouseEvent;
import mx.controls.Alert;
import mx.controls.Button;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.IFlexDisplayObject;
public class ActionButtonItemRenderer extends Button implements IFlexDisplayObject, IListItemRenderer, IDropInListItemRenderer
{
public var btn:Button;
public function ActionButtonItemRenderer()
{
super();
btn = new Button();
btn.label = "Take Action";
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.visible = btn.includeInLayout = true;
}
override protected function clickHandler(event:MouseEvent):void
{
super.clickHandler(event);
Alert.show("Button clicked");
}
}
}
DynamicDataGridButton.mxml :
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600">
<mx:ApplicationControlBar dock="true">
<mx:Button label="Add column" click="init();" />
</mx:ApplicationControlBar>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var arr:ArrayCollection = new ArrayCollection
(
[
{fname:'A',lname:'B'},
{fname:'C',lname:'B'},
{fname:'D',lname:'B'}
]
);
private function addDataGridColumn(dataField:String):void {
var dgc:DataGridColumn = new DataGridColumn(dataField);
dgc.itemRenderer = new ClassFactory(ActionButtonItemRenderer);
var cols:Array = dg.columns;
cols.push(dgc);
dg.columns = cols;
}
private function init():void {
addDataGridColumn("Details");
}
]]>
</mx:Script>
<mx:DataGrid id="dg" dataProvider="{arr}">
<mx:columns>
<mx:DataGridColumn id="dgc1" dataField="fname" headerText="First Name"
width="75"/>
<mx:DataGridColumn id="dgc2" dataField="lname" headerText=" Last Name"
width="150"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
To dynamically create a button in AS3 syntax you would do this:
var button:Button = new Button();
Then after you've created the button, you can set it's properties like this:
button.label = "Click Me!";
And lastly you would add it to one of your items as such:
var dp:Array = [{label: "Button 1", button: button},{label: "Button 2", button: button}];
myDg.dataProvider = dp;
Then you would feed it to your datagrid that is laid out like this:
<mx:DataGrid id="myDG" variableRowHeight="true">
<mx:columns>
<mx:DataGridColumn dataField="label" headerText="Labels"/>
<mx:DataGridColumn dataField="button" headerText="Buttons"/>
</mx:columns>
</mx:DataGrid>
Not sure if that would actually work though, you may have to have an button itemRenderer on the entire column like this example.