views:

60

answers:

1

Hello,

I have a Game-sprite representing a game room with up to 3 players, it works ok. And would like to populate a List component with those Game's, based on an XML data coming from a socket.

I've prepared a simple test case demonstrating my problem -

ListTest.fla (should have a List component in its Library):

import fl.data.*;
import fl.controls.*;

stop();

var xml:XML =
    <data>
      <lobby>
        <user id="OK252342810632" name="Armen"/>
        <user id="DE6948" name="uriuri"/>
        <user id="DE6577" name="Polikari"/>
        <user id="DE7981" name="AlekseyBr"/>
        <user id="DE7880" name="alex554"/>
      </lobby>
      <game id="0"/>
      <game id="9012">
        <user id="OK10218913103" name="Yervand"/>
      </game>
      <game id="9013">
        <user id="OK305894249541" name="chabo"/>
        <user id="OK151358069597" name="Elena"/>
      </game>
      <game id="9007">
        <user id="DE7062" name="lexo"/>
      </game>
      <game id="9010">
        <user id="OK31902424355" name="Nor"/>
        <user id="VK8509030" name="Ilja"/>
        <user id="OK357833936215" name="Jaroslav"/>
      </game>
    </data>;

var game:Game = new Game();
game.x = 10;
game.y = 10;
game.id = xml.game.(@id=='9010').@id;
addChild(game);

var dp:DataProvider = new DataProvider(xml);
var list:List = new List();
list.move(Game.W + 20, 10);
list.width  = Game.W + 20;
list.height = stage.stageHeight/2 - 20;
list.rowHeight = Game.H + 10;
list.setStyle('cellRenderer', Game); 
list.dataProvider = dp;
addChild(list);

Game.as (my custom cell renderer, works ok on its own):

package {
    import flash.display.*;
    import flash.text.*;
    import fl.controls.listClasses.*; 

    public class Game extends Sprite implements ICellRenderer {
        public static const W:uint = 60;
        public static const H:uint = 60;

        private var _id:TextField;

        private var _listData:ListData;
        private var _data:Object;
        private var _selected:Boolean;

        public function Game() {
            mouseChildren = false;
            buttonMode = true;

            var rect:Shape = new Shape();
            rect.graphics.beginFill(0x6666FF);
            rect.graphics.drawRect(0, 0, W, H); 
            rect.graphics.endFill();
            addChild(rect);

            _id = new TextField();
            addChild(_id);
        }

        public function set id(str:String):void {
            _id.text = '#' + str;
            _id.x = (W-_id.textWidth)/2;
            _id.y = (H-_id.textHeight)/2;
        }

        public function get id():String {
            return _id.text;
        }

        public function update(xml:XML):void {
            id = xml.@id;
        }   

        public function set listData(d:ListData):void {
            _listData = d;
        }

        public function get listData():ListData {
            return _listData;
        }

        public function set data(d:Object):void {
            trace(d);
            _data = d;
        }

        public function get data():Object {
            return _data;
        }

        public function get selected():Boolean {
            return _selected;
        }

        public function set selected(sel:Boolean):void {
            _selected = sel;
        }

        public function setMouseState(state:String):void {
        }

        public function setSize(width:Number, height:Number):void {
        }
    }
}

Screenshot: alt text

As you see a standalone game is displayed ok, but as a cellRenderer in the List component it fails - I don't know how to set the id's for the List items.

Please advise me how to fix it

Thank you, Alex

UPDATE:

 public function set data(d:Object):void {
       _data = d;
       id = d.id;
   }

as suggested by Claus works ok now, but how do I get the ids and names of the users? When I set a breakpoint in the above method, then I see that the d.user is just an empty string ""

+1  A: 
  1. In place of your trace statement in Game.as, put: id = d.id;

  2. You might want to pass only the game nodes into the dataprovider:

    var games:XML = <games/>;
    games.appendChild(xml.game);
    var dp:DataProvider = new DataProvider(games);

  3. If you want access to the children of <game>:

    var games:Array = [];
    for each(var g:XML in xml.game) { games.push({ id: g.@id, users: g.user }); }
    var dp:DataProvider = new DataProvider(games);
    Then you can access the users for example like this:
    var users:XMLList = d.user;
    for each(var u:XML in users) {
        trace(u.@id, u.@name);
    }

Claus Wahlers
Thank you! I've traced the set data in debugger and its d argument is really an Object, not XML. Flash seemingly will go through all the 1st level children of dataProvider's XML and create an Object for each of them with attributes as properties (and also with sub-children as properties, but they will be empty strings)
Alexander Farber
My new problem is however, that I need to access the sub-children user for each game, but the d.user is just an empty string :-(
Alexander Farber
If you want access to children, you'd probably have to pre-parse the XML into an Array of Objects that hold the data you need in your data provider, and pass that Array instead of the XML.
Claus Wahlers
I updated my answer with a rough code example, see 3.
Claus Wahlers
Thank you for coming back and answering that
Alexander Farber