AdvancedDataGrid : Conditionally change the icon of the leaf node - actionscript-3

Introduction: I have a flat ArrayCollection of object's, which i group to create the dataProvider for an AdvancedDataGrid. In this AdvancedDataGrid i have different branches representing different type of tasks. I want to conditionally change the icon for the leaf nodes in the AdvancedDataGrid based on a date field stored in each object.
For this purpose lets say each Task object contains an id and an updatedDate (Representing when the task was last updated). If the task has not been updated in the last five days (updatedDate+5 < today) the icon of that leaf node(Task) should be red, in constrast to the opposite the leaf icon in the AdvancedDatagrid should be green, e.g. like the image below. In this case task 35 has not been updated in the last 5 days, while 13 and 39 have.
Question: How do i change the leaf icons in the ADG based on the updatedDate of the underlying object? I would think that i have to extend AdvancedDataGrid and override some method, but which and how? Any type of guidance for achieving this particular task is much appriciated!
I have seen easy ways of changing the open and closed icons on the web, but no way of conditionally changing an open node's icon :)
Update: After applying #takteek groupIconFunction solution which always returned the same icon:
The problem is that I need the leaf node's icons changed, and not the branches.
SOLVED: Used #takteek's answer, with the exception of using iconFunction instead of groupIconFunction, because i wanted to change the leaf node's icons, and not the groupIcons :)

Your two options are:
Specify agroupIconFunction for the data grid. This gets passed the current item and you return which icon to use, or null to use the default.
Create a subclass of AdvancedDataGrid and override makeListData. This function is responsible for creating the AdvancedDataGridListData object that gets passed to the renderers. You can change the icon and disclosureIcon properties on the list data to what you want. This is probably unnecessary unless you need more control.
Create your own item renderer based on AdvancedDataGridGroupItemRenderer.

Related

Dynamically changing the bound entity of a list box on a canvas

I'm wondering if anyone has come across this issue.
I have two radio buttons on a canvas app that I am attempting to control the values displayed within a list box.
RadioButtons.Items: ["SomeValueA","SomeValueB"]
The list box control should be getting reset whenever the value of the radio button changes.
UpdateContext({resetList: !resetList});
UpdateContext({resetList: !resetList});
Reset(lbListbox);
lbListbox.Reset: resetList
For the list box itself I have the following for Items:
Switch(
RadioButtons.Selected.Value,
"SomeValueA",
Sort(
EntityA.FieldName,
Descending
),
"SomeValueB",
Sort(
EntityB.'Some other field name',
Descending
)
)
The problem is when I select 'SomeValueA' the list box properly populates with the values from EntityA.FieldName but when I then select 'SomeValueB' from the radio buttons the list box blanks out with empty records. There appears to be items in the list box that I can scroll through and select but not see.
If I put two list boxes on the screen and set their Items event to the specific entity the values show up properly in both list boxes so I know the entity naming/field is correct.
I've tried it without the reset of the list box, I've tried it using collections made out of the entity records.
Has anyone come across this who maybe has a solution. I was going to try to put two list boxes on top of one another and either hide/show or bring to front the active list but that also doesn't want to work.
thanks!
(Received this post from another source, figured I might as well post back here as well)
Got this to work, but it was a bit finicky. The catch seemed to be giving the List a value-pairing table, instead of just a list of values.
First I collected the Option Sets from CDS, and added a column to indicate the source name, for reference. This could easily be combined into a single collection, and then filtered later but I was thinking simple.
ClearCollect(colOptionSet1,AddColumns(Choices('Ownership (Accounts)'),"appSource","Ownership"));
ClearCollect(colOptionSet2,AddColumns(Choices('Preferred Method of Contact (Accounts)'),"appSource","Preferred Method"));
Next added a Radio button identical to yours.
Then added a List control with Items equal to
If( Radio1.Selected.Value = "SomeValueA", colOptionSet1, Radio1.Selected.Value = "SomeValueB", colOptionSet2 )
You may need to use the right-side property pane to toggle between Value and "appSource" (from collections above), but this did allow me to toggle between two separate Option Set fields in a single list.
Patching/writing this back is gonna be another hurdle. 😝

Creating a nicely coded level select screen

Currently developing my first full flash game, and I'm now implementing multiple levels, which means I have to make a level select screen. I have no problem with actually accomplishing this, but the only way I know how to do this would be to make a different level select screen available every time somebody passed a new level (ie, after passing level 2, now there are 2 buttons available, for level 1 and 2 instead of just level 1).
Of course, this is highly inefficient. I want to be able to do this for all my levels in one go. I already know in advance that I will be having 9 levels, so a 3x3 grid system of buttons is possible (maybe using 2 for loops, for x and y position?).
Navigating between level select and other pages is no problem, I should be able to do that. My real problem is creating the actual level select screen to display different amounts of clickable buttons depending on how far one has progressed in the game. I mean I'm guessing I just create some boolean values for the user, and once a level is passed I change those booleans to true, then link the boolean to creating a button instead of a static text field. Then would I just position each button individually on the level select screen? If somebody could shed some light ( and by light I mean code =p ) about how to accomplish making this type of level select screen, it would be greatly appreciated, particularly the part about adding the buttons to the stage vs. the textfields.
Also, is it a waste to create 9 different buttons? It would be nice to just create 1 button and then just change the text field on them to display the level number. Can I accomplish this using a dynamic text field and just altering the text in that text field?
Basically yes, you can do whatever you see fit, just prepare for all of this. This is mostly architecture question than actual programming question. About progress, you can either track the highest available level and only display those that are available, or display level progress (say one level was complete with 1 star, the other with 2 stars, and you make buttons with stars on them), etc. Also, you might look at say Angry Birds level selector, it has 15 buttons, why could you not make 9?
About how to add a custom button to stage - first, it's better if you wrap the whole level selector into a Sprite, write AS3 code for it having level buttons placed at specific coordinates, a close button (aka "no I want to review other options before selecting level" one), other data like a text field with level name, etc etc, whatever you see fit. An example (with only level buttons, mostly in pseudocode):
public class LevelSelector extends Sprite {
private static const thumbnailClasses:Array=[Level01Bitmap,Level02Bitmap,...];
// embed these
private var gridXOffset:Number=60;
private var gridYOffset:Number=60;
private var gridXDimension:int=3; // how many buttons in row
private var gridXBase:Number=30;
private var gridYBase:Number=10;
// other initialized data
private var buttons:Vector.<LevelButton>; // buttons stored here
public function LevelSelector() {
buttons=new Vector.<LevelButton>();
// other initialization
for (var i:int=0;i<thumbnailClasses.length;i++) {
var b:LevelButton=new LevelButton();
b.x=(i%gridXDimension)*gridXOffset+gridXBase;
b.y=Math.floor(i/gridXDimension)*gridYOffset+gridYBase;
b.picture=(new thumbnailClasses[i]()).bitmapData;
// assuming thumbnails are embedded bitmap class names
addChild(b);
b.enabled=levelIsAvailable(i); // query level availability
b.stars=getLevelPerformance(i); // query how many stars to draw
b.addEventListener(MouseEvent.CLICK,buttonPressed); // listen for mouse
buttons.push(b);
}
}
private function buttonPressed(e:MouseEvent):void {
var level:int=buttons.indexOf(e.target);
var b:LevelButton=e.target; // if need to do something with the button
// query correctness and navigate to level screen
}
}
It sounds like you need to break the problem down into smaller steps. I'm not sure if you're using the Flash timeline or external .as Classes. I'd recommend using Classes as you can be much more flexible about what you display on screen. If you're not used to using Classes, the following probably won't make much sense...
In your main Document.as Class you could keep track of which levels the player has completed (perhaps in an Array of Boolean values corresponding to the level numbers). When a LevelSelect page is needed, make a new LevelSelect page and pass the _levelsCompleted Array as a parameter. The passed array can be used by the LevelSelect Class instance to determine how many LevelButtons are needed. Loop through the passed Boolean array and if an index value is true, add a LevelButton. Each LevelButton could be passed its level number (the loop counter) which could be used in its TextField to identify it (remember Array indexes are zero indexed, so level '1' might actually be '0').
If this doesn't make any sense, let me know.

what happens when i say arrayCollection.addItemAt(object,0);

Lets say i have an Array collection, filled with some elements. If i say
myArrayCollection.addItemAt(object,0);
What exactly happens here? Does all the elements gets shifted rigthwards? or element at 0th position gets replaced with new one?
To summarize, the reason there are two different methods, addItemAt() and setItemAt(), is because one of them adds a new item (not replacing any of the existing ones), and the other sets/overwrites the existing index.
For more info, check out the ArrayCollection documentation.

Combining a multiple strings and arrays to one dataProvider for a spark List

I'm struggling with this one, what I need to do is combine 5 arrays with 5 individual strings (which have come from a JSON webservice) into one single list item in FlashBuilder Burrito.
The web service returns data as follows
Title(String)
Array[0[name, size, imageurl]][1[name, size, imageurl]][2[name, size, imageurl]]
Title_1(String)
Array_1[0[name, size, imageurl]][1[name, size, imageurl]][2[name, size, imageurl]]
Title_2(String)
Array_2[0[name, size, imageurl]][1[name, size, imageurl]][2[name, size, imageurl]]
Title_3(String)
Array_3[0[name, size, imageurl]][1[name, size, imageurl]][2[name, size, imageurl]]
And so on. I've pulled these out successfully and each one traces in the debugger, although as I need them all in the same list I'm struggling to establish them as a dataprovider together.
If I push the strings and arrays together it is impossible to read properly, as the main Titles are at a different level to any descriptors for the products which are in the arrays. So I'm sort of stuck!!
Any advice on how best to approach this?
Cheers
Really depends on the design of the application on how to best approach this. If the list is going to be sortable on the properties (Name, Size, Price etc) then instead of labels you might want to push the "type" into the array and have a way of showing this in the item renderer. If the items are supposed to be separated by type, but also sortable you might want to look at using an accordion type control and having separate lists.
Anyhow what you want to do is concatenate the arrays into a single array and push the "Title" into the object as a property. This way you can at least sort on the title so the items appear in the correct order in the single list.
Otherwise you could just create a custom control with 5 different lists stacked on top of each other (With no scrollbars) and have the custom control handle scrolling of all 5 lists with a single scroll bar.

Show itemRenderer in specific DataGrid rows... others empty

I have a DataGrid populated via an Array. The last column in the DataGrid uses an ItemRenderer (Button). I want to show the Button in certain rows but not in others (leave those empty). I've looked everywhere for an example or even a clue how to do this (tried labelFunction on DG, etc.) but can't find anything about it. Any help would be appreciated. Thanks!
Okay... with (lots of) help, figured it out.
First off, I'm not sure why the itemRenderer requires a container but it does. The array must also be checked from the itemRenderer and not from the main application... again, I don't know why since the debugger shows it going through the exact same loop/events, etc.).
If interested here's the relevant parts of the code:
Main App:---
{col1:'', col2:'', col3:'', col4:'', col5:'', col6:'', col7: '', col8:'', col9:'', col10:'', col11:'yo'}];
public function initData():void
{ xferSchedule.dataProvider = schedArray; }
]]>
an item renderer does not have to be a container, it has to implement IDataRenderer (a Button does not). One could extend Button and implement this interface to get a simple button renderer. If you want it to display conditionally, you will accomplish this by handling those conditions within the renderer based on the data.
Now this might get slightly complex. I would recommend you to define you an XML instead of Array of Objects. If the node has the type property button, then it would create button at that cell whose value type is button.
How to create a button dynamically inside a grid which is yet again dynamic?
This might end into the whole component being dynamic.