How to show list of components in Flex - actionscript-3

I'm building a multiplayer game which when connecting to the server, the server sends back a list of available rooms (each room has MaxPlayers,MinRank,TableId,TableName,Password) so everytime I recieve these 5 strings, I create an instance of Mxml UI Component I have created and fill it with the relevant details.
In the main.MXML i've added an AS3 script variable to hold the GameInstances object i've created when rcvd data back from the server:
private var gameInstances:ArrayCollection = new ArrayCollection();
GameInstance.mxml is a component that has UI components in it and AS3 script to set some data.
When rcving data from the server in main.mxml :
var gameInstance:GameInstance = new GameInstance();
gameInstance.setTablePlayers(rcvdMsg[1]);
gameInstance.setTableMinRank(rcvdMsg[2]);
gameInstance.setTableId(rcvdMsg[3]);
gameInstance.setTableName(rcvdMsg[4]);
gameInstance.setTablePassword(rcvdMsg[5]);
gameInstances.addItem(gameInstance);
gameInstances holds objects of that mxml component.
How do I show this component visualy on the main.mxml?
I have a in main.mxml that I want visually show inside it the GameInstance objects.
This is how GameInstance.mxml looks like, I want the s:List to hold for each game a UI object like that(to show it ofcourse)

OK, if you using the gameInstances arraycollection as a data provider for tableList then you need to do a few things.
First, you need to make your gameInstances arraycollection [Bindable]
Then, you need to add data to the array collection as code you posted shows you are.
Next, you have to Create a custom item renderer for your tableList.
Finally, when you are done changing data/adding/removing objects from the gameInstances arraycollection you need to gameInstances.refresh();
[EDIT]
create a file named myListRenderer.mxml and put this code in it
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
override protected function commitProperties():void{
// this is where you assign your values
// this function gets called every-time the list scrolls
super.commitProperties();
players.text = this.data.setTablePlayers
minRank.text = this.data.setTableMinRank;
tableId.text = this.data.setTableId;
tableName.text = this.data.setTableName;
tablePassword.text = this.data.setTablePassword;
}
]]>
</mx:Script>
<mx:Label id="players" />
<mx:Label id="minRank" />
<mx:Label id="tableId" />
<mx:Label id="tableName" />
<mx:Label id="tablePassword" />
</mx:VBox>

If I understand the question, when you create components in ActionScript, you have to add them to a container before they'lls how up in the UI. If you have an array of components, you can just loop over that array and add each component as a child on a container. The main application file is a container, so you can do something like this:
for each(var myComp:UIComponent in myArrayList){
addChild(myComp);
}
It would be unusual to take this approach. Usually you just add the component to the parent container as you create them.

Related

How can I make Flex Busy Indicator load early?

I'm building a mobile app with Flash Builder 4.6 and AIR.
My Main.mxml class -- a ViewNavigatorApplication -- references a splash screen set to a minimum time of 6 seconds. After the splashscreen disappears, there's a period of a couple of seconds during which the content area of the screen is just blank white -- and that's when I need the Busy Indicator to appear.
EDIT: Additional Code, as requested:
In the Main.mxml class:
protected function viewnavigatorAppInitializeHandler(event:FlexEvent):void
{
//checks various criteria to determine which data to load, ie which service call
// to make. When that is determined, code calls setUpModel().
}
private function setUpModel():void {
Model.Instance.initialize(); //adds listeners in the model,
//makes service call. Data is returned and parsed in the event handler.
//APPLICATION_MODEL_LOADED event is then dispatched, and handled here
Model.Instance.addEventListener( Model.APPLICATION_MODEL_LOADED, modelReadyHandler );
}
private function modelReadyHandler(e:Event):void
{
//Busy Indicator only appears *after* the HomeListView is loaded.
//I need it to appear *while* these calls are being made.
navigator.pushView(HomeListView); //this is my First View
}
So I think the question is: what is it that is being displayed before HomeListView? If it's Main.mxml -- the ViewNavigatorApplication -- then how do I avoid the 'not assignable' error?
In HomeListView:
[Bindable] private var categoryList:ArrayCollection = new ArrayCollection();
private function viewActivateHandler():void
{
//the service call has been made, and data is ready to be loaded into the control
categories = Model.Instance.Categories;
I've tried this inside HomeListView:
<s:Group width="100%" height="100%">
<s:BusyIndicator
id="busy"
visible="true" symbolColor="blue"
horizontalCenter="0" verticalCenter="0"
rotationInterval="100" />
</s:Group>
It works. But the problem is it only appears once HomeListView has loaded. I thought that the blank white was HomeListView, just before the list appeared. But it isn't.
So then I tried putting the above code into the Main.mxml file. But I got the following error:
'spark.components.Group' is not assignable to the default property, 'navigationStack', of type 'spark.components.supportClasses.NavigationStack'.
So where can I put this BusyIndicator so that it covers the blank space before HomeListView appears?
I've figured out a way to do this.
From the documentation:
"Unlike Application, ViewNavigatorApplication is not meant to accept UIComponent objects as children. Instead, all visual components should be children of the views managed by the application."
That is why I was getting the error. So for my first View, I created a simple View called HolderView which contains the BusyIndicator:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HolderView">
<s:Group width="100%" height="100%">
<s:BusyIndicator
id="busy"
visible="true" symbolColor="blue"
horizontalCenter="0" verticalCenter="0"
rotationInterval="100" />
</s:Group>
Then, from my Main.mxml file, I first load that HolderView.
private function setUpModel():void {
Model.Instance.initialize();
navigator.pushView(HolderView);
Model.Instance.addEventListener(Model.APPLICATION_MODEL_LOADED, modelReadyHandler );
}
Once the data has come back -- on the Model.APPLICATION_MODEL_LOADED event listener -- that is when I will load HomeListView:
private function modelReadyHandler(e:Event):void
{
navigator.pushView(HomeListView);
}
This works. Hope it helps someone with same problem!

Setting the folder icon of a tree column (based on row data) in AdvancedDataGrid in Flex

Is it possible to change the folder icon of a tree column in an AdvancedDataGrid based on the data of that row?
I have an AdvancedDataGrid that is displaying HierarchicalData (from XML data) in a tree format. I want to display a different icon for the folder icon based on the XML data for each row. The only obvious way to change the folder icons at all is to set the folderOpenIcon and folderClosedIcon properties of my AdvancedDataGrid, but that sets the folder icon for all rows. I tried using the AdvancedDataGrid function "setItemIcon", but that doesn't seem to work.
I have some ColumnRenderers in this AdvancedDataGrid that display different icons in other columns based on the row data, but I haven't found a way to do this with the main tree column. I'm guessing it would be similar to using a ColumnRenderer, but maybe using something like a GroupItemRenderer.
This should be possible via an groupIconFunction like this:
<mx:AdvancedDataGrid groupIconFunction="getGroupIcon">
<mx:columns>
<mx:AdvancedDataGridColumn headerText="Name" dataField="name"/>
</mx:columns>
</mx:AdvancedDataGrid>
<fx:Script>
[Embed(source='/assets/company.png')]
private static const COMPANY_ICON: Class;
[Embed(source='/assets/customer.png')]
private static const CUSTOMER_ICON: Class;
private function getGroupIcon(item:Object,depth:int):Class
{
if (item is Company)
return COMPANY_ICON;
if (item is Customer)
return CUSTOMER_ICON;
// null = default icon
return null;
}
</fx:Script>
There is also an example in Adobe's Flex online reference which demonstrates how to use the groupIconFunction and groupLabelFunction properties.

Dynamically Selecting Embedded Image For A List Based on data result from SQLite

I have a Spark list which needs different images loaded into it based on data coming through from an SQlite query.
In SQLite I have a column called "IconId" which for example might contain the value "1", "2", "3" etc representing an icon image.
My Icon images are Embedded in a class called "ImageResources" as follows:
[Bindable]
public class ImageResources
{
[Embed(source="../assets/caticons/icon1.jpg")]
public static var Ic1Cla:Class;
[Embed(source="../assets/caticons/icon2.jpg")]
public static var Ic2Cla:Class;
}
Then I have the itemrenderer for my Spark List which has a Bitmap which I use to set the icon I want to use for the list item like this.. This is a static example which works:
<s:BitmapImage source="{ImageResources.Ic1Cla}"
x="5" y="2">
</s:BitmapImage>
My question is..Can I dynamically concatenate the BitmapImage source somehow to something that will take the number coming from my SQLite data e.g "1" into something like this:
<s:BitmapImage source="{ImageResources.Ic[data.IconId]Cla}"
x="5" y="2">
</s:BitmapImage>
Obviously this doesn't work but I'm not sure if it's a simple syntax issue or whether it could even be done in this manner.
Any help would be much appreciated.
You can dynamically access a variable such as:
<s:BitmapImage source="{ImageResources['Ic' + data.IconId + 'Cla']}" />
There are other approaches, such as using a state system. By setting the current state as in currentState = "image" + data.IconId; this could be implemented as:
<s:states>
<s:State name="image1" />
<s:State name="image2" />
</s:states>
<s:BitmapImage source.image1="{ImageResources.Ic1Cla}"
source.image2="{ImageResources.Ic2Cla}" />

How can I edit the objects within custom AS3 components using MXML?

I'm writing a Flex application using Flash Builder 4 and I'm having a bit of trouble with an AS3 object. Essentially, it is a BorderContainer, with a few buttons and images, and programming logic that determines how these interact with eachother and a database.
What I want to be able to do is configure the layout/style of the inner components using MXML and CSS. I can configure the inherited objects, but not ones that I have defined...
For example, in my MXML. I can modify the (inherited) borderstroke variable of myContainer like so;
<IE:MyContainer>
<IE:borderStroke>
<s:LinearGradientStroke weight="10" rotation="270">
<s:GradientEntry color="0xF655E5"/>
<s:GradientEntry color="0x6600CC"/>
</s:LinearGradientStroke>
</IE:borderStroke>
</IE:MyContainer>
However, I can't edit the nextButton variable (which is of type Button) like this;
<IE:MyContainer>
<IE:nextButton width="100" height="30" left="10%" bottom="10%"/>
</IE:MyContainer>
If I try, I get the compile error "Could not resolve to a component implementation".
What do I need to do to make this work?!
Thanks in advance,
Aidan
EDIT:
Here's the main method of MyContainer (actually named InvestigativeEnvironment).
The call to defineTestInvestigativeEnvironment() is what takes care of setting up the objects and action listeners and such. What I want to do is change the layout and appearance of these visual components in MXML (nextButton, prevButton, toolbox, displayArea). I want to be able to set their height, width, background, x, y, horizontalCenter, etc like I can to a button that I add to a container via MXML.
public class InvestigativeEnvironment extends BorderContainer
{
private var toolbox:Toolbox;
private var bodySystem:BodySystem;
public var nextButton:Button;
public var prevButton:Button;
private var displayArea:Group;
private var image:Image;
private var toolDisplayArea:Group;
public function InvestigativeEnvironment()
{
super();
//create 'Next' button and event listener
nextButton = new Button();
nextButton.addEventListener(MouseEvent.CLICK, nextViewAngle);
nextButton.label = "Next";
this.addElement(nextButton);
//create 'Prev' button and event listener
prevButton = new Button();
prevButton.addEventListener(MouseEvent.CLICK, prevViewAngle);
prevButton.label = "Prev";
this.addElement(prevButton);
//define investigative environment by creating models.
defineTestInvestigativeEnvironment();
//Instantiate the Group that contains the model image and tool overlays
displayArea=new Group();
//Instantiate the image that is used to display the model
image = new Image();
image.source=bodySystem.getImage();
image.horizontalCenter=0;
image.verticalCenter=0;
displayArea.addElement(image);
//add toolOverlayContainer to the display area ABOVE the model image
toolDisplayArea = new Group();
toolDisplayArea.verticalCenter=0;
toolDisplayArea.horizontalCenter=0;
displayArea.addElement(toolDisplayArea);
this.addElement(displayArea);
//add toolbox to display
toolbox = new Toolbox(toolDisplayArea);
toolbox.replaceTools(bodySystem.getToolGroup());
this.addElement(toolbox);
}
I can't understand what is your problem with editing button in particular, sorry for that. But I have a lot of notices about your InvestigativeEnvironment which code you've attached.
First, you haven't follow Flex components livecycle (see here or here). So in your code you should add and configure children in createChildren() method.
But anyway you can't use your container to add children both with MXML and from code. If your adding custom components code will be executed first MXML (in your implementation with adding them in constructor it is so) all the MXML tags just remove all your added content (anyway result will be unpredictable). In other case it will be very hard to control instance's order.
I can suggest you to declare your nextButton etc as skin parts and perform their positioning in skin. This way these internal controls will be a part of border and you can add MXML children without any problem. And you can configure them within partAdded() method.
It turns out that I wasn't quite asking the right question. I wanted to edit the components, but specifically the layout and color type attributes of them.
What I need to do is set the id of the components, and then target them using CSS.
For my nextButton, I add the ID like this;
nextButton.id="nextButton";
Then I can lay it out in the MXML file (or external stylesheet) like this;
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace IE "InvestigativeEnvironment.*";
IE|InvestigativeEnvironment s|Button {
chromeColor: #336666;
}
#nextButton {
bottom: 100;
right: 5;
}
</fx:Style>

How to create dynamic variable vbox in actionscript

I have to create several vbox-es in a for each loop.
Now I want to do something like this.
formsArray["vb"+counter] = new VBox;
formsArray["vb"+counter].visible = true;
add labels etc.
I can't get this thing to work. Anybody any idea how to create dynamic variable names for my vbox-es?
Thanks
First off, to use an associative array, you need to use an Object and not an Array (perhaps you already are, then never mind).
You can achieve what you want to do the following way:
var vbox:VBox;
var formsArray:Object = new Object();
var counter:int = 0;
for each(<statement>)
{
vbox = new VBox();
formsArray[("vb" + counter.toString())] = vbox;
counter++;
}
The VBox's visible property is true by default, so no need to explicitly set it.
Answer to additional question in comments:
You don't really need to make use of dynamic references to do what you want to do. You'd be best of creating a custom component for this, extending the VBox class, by creating a new MXML class with VBox as the root tag. Something along these lines:
<mx:VBox ... >
<mx:Button ... click="btnClickHandler()"/>
<mx:Script>
<![CDATA[
// Toggles visibility of the VBox
private function btnClickHandler():void
{
visible = !visible;
}
]]>
</mx:Script>
</mx:VBox>
Then you can just instantiate as many of these custom VBox:es as you need. However, making the VBox invisible will make the contained button invisible as well, making it difficult to click it again. :) You probably want to address that. Anyways, I hope this will point you in the right direction.