Detecting Orientation Change with Event Listener - actionscript-3

I'am work on ActionScript mobile project , i'am using starling with AS3 , i try to add event listener to detect ORIENTATION_CHANGE event in starling class but it will not detect the change , if i add event listener in AS3 class (Main class) will detect and will call the starling class again .
main class of AS3 :
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.StageOrientationEvent;
import starling.core.Starling;
public class mainClass extends Sprite
{
private var myStarling:Starling;
public function mainClass()
{
super();
stage.addEventListener(Event.RESIZE,onResize);
stage.addEventListener(flash.events.StageOrientationEvent.ORIENTATION_CHANGE,shangedOr);
}
private function shangedOr(e:StageOrientationEvent):void
{
// code
}
private function onResize(e:Event):void
{
myStarling = new Starling(Main,stage);
myStarling.start();
}
}
}
starling class : i add new AS class and make it starling class
package
{
import feathers.controls.ScrollContainer;
import feathers.layout.VerticalLayout;
import feathers.themes.AeonDesktopTheme;
import flash.events.Event;
import feathers.controls.Label;
import feathers.controls.TextInput;
import flash.events.StageOrientationEvent;
import org.osmf.layout.VerticalAlign;
import starling.display.DisplayObject;
import starling.display.Sprite;
import starling.display.Stage;
import starling.events.Event;
public class starlingClass extends starling.display.Sprite
{
private var newLayout:VerticalLayout = new VerticalLayout();
private var container:ScrollContainer = new ScrollContainer();
public function starlingClass()
{
super();
this.addEventListener(starling.events.Event.ADDED_TO_STAGE,addToStage);
this.addEventListener(flash.events.StageOrientationEvent.ORIENTATION_CHANGING,orientationChange);
}
private function addToStage(e:starling.events.Event):void
{
this.theme = new AeonDesktopTheme( this.stage );
drawComponent();
}
private function orientationChange(evt:StageOrientationEvent):void
{
// orientation will not responce to change orientation.
}
private function drawComponent():void
{
var button:feathers.controls.Button = new feathers.controls.Button();
button.label = "Click Me";
var newLabel:Label = new Label();
newLabel.text = "hello world";
var txt:TextInput = new TextInput();
var layout:VerticalLayout = new VerticalLayout();
var container:ScrollContainer = new ScrollContainer();
container.layout = layout;
container.addChild(button);
container.addChild(newLabel);
container.addChild(txt);
this.addChild( container );
layout.paddingTop = 10;
layout.paddingRight = 15;
layout.paddingBottom = 10;
layout.paddingLeft = 15;
layout.gap = 5;
}
}
}
the problem : mainClass.as will detect the orientation change and will call starlingClass.as and no component shown . starlingClass.as will never detect the orientation change maybe because i detect an flash event inside starling class ..
any help

answer is :
there is a mistake in my code , the problem in this function :
private function onResize(e:Event):void
{
myStarling = new Starling(Main,stage);
myStarling.start();
}
because every change orientation will call onResize method , to call it again of starling.
solution is very simple :
private function onResize(e:flash.events.Event):void
{
if (myStarling == null)
{
myStarling = new Starling(Main,stage);
myStarling.start();
}
}

You should add event listener over nativeStage like below:
this.nativeStage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, onOrientationChanging);
Because "stage" you have used is Starling stage.

Related

Actionscript making intro of a game

I'm making a game in full classes. so the timeline is empty. But I want to use another scene for the game intro, after the intro, it will proceed to the main menu of the game which I have created. Anyone got an idea? I haven't found any since a week ago... I don't really know about how to operate scenes from code in classes. Please help. Thanks!
Here is the main code :
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.MovieClip;
public class Main extends Sprite
{
public var field:Array;
//CALL EVERY CLASS
public var _money:Money = new Money();
public var _gold:Gold;
public var _hero:Hero;
public var _enemy:Enemy;
private var _pause:MovieClip = new Pause();
private var pauseLayer:MovieClip = new PauseLayer();
private var ts:TitleScreen;
public function Main():void
{
ts = new TitleScreen();
addChild(ts);
}
//GAME FUNCTION
public function onStage():void
{
_hero = new Hero(this);
_enemy = new Enemy(this);
_gold = new Gold(this);
setupField();
_gold.goldSet(stage);
_money.addText(stage);
_hero.displayHero(stage);
_enemy.displayEnemy(stage);
setPause();
_pause.addEventListener(MouseEvent.CLICK, pauseGame);
}
private function setPause():void
{
addChild(_pause);
_pause.x = 620;
_pause.y = 50;
_pause.buttonMode = true;
}
private function pauseGame (e:MouseEvent):void
{
stage.frameRate = 0;
addChild(pauseLayer);
pauseLayer.alpha = 0.5;
pauseLayer.parent.setChildIndex(pauseLayer,numChildren-1);
}
//SET UP FIELD ARRAY
private function setupField():void
{
var fieldSprite:Sprite=new Sprite();
addChild(fieldSprite);
fieldSprite.graphics.lineStyle(4);
field=new Array();
for (var a:int=0; a<6; a++)
{
field[a]=new Array();
for (var b:int=0; b<10; b++)
{
field[a][b]=0;
}
}
//DRAW FIELD
for (var i:int=0; i<5; i++)
{
for (var j:int=0; j<9; j++)
{
fieldSprite.graphics.drawRect(75+65*j,50+75*i,65,75);
}
}
}
}
}
Titlescreen class :
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.display.Sprite;
public class TitleScreen extends Sprite
{
private var playBtn:MovieClip = new Resume();
public function TitleScreen()
{
playBtn.x = 50;
playBtn.y = 50;
playBtn.addEventListener(MouseEvent.CLICK, Play);
}
private function Play(e:MouseEvent):void
{
trace("a");
}
}
}
The most simple way would be using wrapper Sprites to hold each set of objects you probably want to be available as whole, say main menu, upgrades, storyline, etc etc. Then you just shift them in and out of display list to display corresponding "scene" with your Main class responsible of transition flow. But to do this you need to shift your game core functionality out of Main class into say Game class. That's how I have done the same thing in my game:
public class Main extends MovieClip {
private var so:SharedObject;
private var ui:UserInterface;
private var ts:TitleScreen;
private function init(e:Event = null):void
{
ui = new UserInterface();
ts = new TitleScreen();
ts.newButtonClicked = newGame;
ts.loadButtonClicked = loadGame;
ui.gotoMapBehavior = wentToMap;
addChild(ts);
}
Here, UserInterface is a class that has gaming logic inside, and TitleScreen is a main menu class. The functions are callbacks in Main:
private function newGame():void {
removeChild(ts); // hide title
if (!contains(ui)) addChild(ui);
SoundManager.playMusic(SoundManager.MUSIC_LEVELSELECT);
}
private function loadGame():void {
newGame();
ui.loadBattle(); // this should make UI load the battle from shared object (either supplied or received by itself)
}
private function wentToMap():void {
// we have just executed "go to map" from UI
removeChild(ui);
addChild(ts);
checkSO();
SoundManager.playMusic(SoundManager.MUSIC_INTRO);
}
The actual gaming logic does not interact with Main at all, except for shared object which is common for the entire project, but the link is received normally via SharedObject.getLocal(someName). The code is ugly, but could do for starters.
Save your game as SWF and make another project with timeline-animated intro. When the intro ends, make your project to load your game. Loader class can load other swf files. So, you don't need to edit your game classes.

Flash Builder 4.6 Mobile Flex AS3: How to communicate with embedded SWF

I have a Flash Barcode scanner (camera) and want to use it in a mobile project to scan QR-Codes. It would be nice that it is possible to re-use this SWF and embedded it into a mobile Flex application. The SWF is made in Flash CS5.
So far, embedding (and add it to the stage and showing it) is successful but how do i communicate with the SWF? For example calling a function of it or by using events.
Here is a code snippet:
[Embed(source="../cam/cam.swf")]
private var cam:Class;
....
....
public const EVT_SNAPSHOT : String = "onSnapShot";
public var camera : Object;
public function onInit(e:Event) : void
{
this.camera = new cam();
this.camera.addEventListener(Event.ADDED_TO_STAGE, this.cameraInit );
this.stage.addChild( this.camera as DisplayObject );
}
private function cameraInit(e:Event):void
{
trace( 'Added to stage' );
this.stage.addEventListener( EVT_SNAPSHOT, this.cameraDoScan ); // does not bind?
trace( this.camera.hasOwnProperty('getAppInfo') ); // shows 'false'
}
private function cameraDoScan(e:MouseEvent):void
{
trace('MouseClick!');
}
Does anyone know to communicate with this 'thing'?
The most functional way to use external swf module is to load it into current ApplicationDomain, so you will have access to all classes contained in this loaded swf:
package
{
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.utils.ByteArray;
import flash.utils.getDefinitionByName;
public class astest extends Sprite
{
[Embed(source="/../assets/art.swf", mimeType="application/octet-stream")]
private static const art:Class;
public function astest()
{
var artBytes:ByteArray = new art() as ByteArray;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onArtLoaded);
loader.loadBytes(artBytes, new LoaderContext(false, ApplicationDomain.currentDomain));
}
protected function onArtLoaded(e:Event):void
{
var domain:ApplicationDomain = ApplicationDomain.currentDomain;
if(domain.hasDefinition("welcome_view"))
{
var moduleClass:Class = domain.getDefinition("welcome_view") as Class;
var module:Object = new moduleClass();
//module.moduleFunction();
addChild(module as DisplayObject);
}else
{
trace("loaded swf hasn't class 'welcome_view'");
}
}
}
}

Redirect player to Game over screen on timer completion

Okay, i'm very new to Actionscript 3
I would like my timer to direct whoever is playing my game to go the 'Game Over' screen on timer completion (00:00). At the moment I am getting an error saying "1067: Implicit coercion of a value of type Class to an unrelated type flash.display:DisplayObject."
Any ideas?
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class SecondCounter extends MovieClip {
private var myTimer:Timer=new Timer(1000,0);
private var secs:Number=10;
private var mins:Number=0;
private var sec_t:String;
private var min_t:String;
var screen7:EndScreen;
public function SecondCounter() {
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
myTimer.start();
}
private function timerHandler(evt:TimerEvent):void {
if (secs==0) {
if (mins==0) {
addChild(EndScreen);
} else {
mins--;
secs=59;
}
} else {
secs--;
}
if(secs<10){
sec_t = "0"+String(secs)
} else {
sec_t = String(secs);
}
if(mins<10){
min_t = "0"+String(mins) +":"
} else {
min_t = String(mins)+":";
}
secondField.text = min_t + sec_t;
}
}
}
The problem is that you are attempting to add the Class itself to the screen as opposed to an instance of the class.
var screen7:EndScreen;
// ....
addChild(EndScreen);
EndScreen is the class. This is the blueprint of how to create an actual EndScreen object. Screen7 is an instance of the EndScreen class (EndScreen class = blueprint, screen7 instance = actual built house).
However you have not actually instaniated screen7, so do that:
var screen7:EndScreen = new EndScreen();
Now you can add that instance to the display:
addChild(screen7);

Flex 4.5 Not listening to custom event dispatched in custom AS class

I have the following situation:
I have an event handler, that displays small messages in my application's statusbar.
These messages get passes through by dispatching events from custom components.
A simple message could be like "HTTP Error" or so.
Now, the main event listener, in the main application file, listens to the event dispatched by any custom component, but seems to refuse listening to events dispatched by custom AS classes.
Here is my code for the custom event:
package main.events
{
import flash.events.Event;
public class ShowNoticeEvent extends Event
{
public var message:String;
public static const SHOW_NOTICE:String = "showNotice";
public function ShowNoticeEvent(type:String, msg:String, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
this.message = msg;
}
override public function clone():Event
{
return new ShowNoticeEvent(type, message);
}
}
}
This is the event listener in the main application file:
addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
And this is the custom AS class that dispatches the custom event. I pasted all the code, so you could see the whole part of it.
package components.dashboard
{
import components.dashboard.models.*;
/* Event imports */
import flash.events.*;
import main.events.*;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="showNotice", type="main.events.ShowNoticeEvent")]
public class Controller extends UIComponent
{
private var baseUrl:String;
public function Controller(baseUrl:String)
{
this.baseUrl = baseUrl;
}
public function getRunningQuotations():void
{
var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();
execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations");
}
public function getRecentProjects():void
{
var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();
execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
}
public function getLatestCustomers():void
{
var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();
execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
}
private function execService(url:String, listener:Function, component:String):void
{
var basicService:HTTPService = new HTTPService(baseUrl);
basicService.showBusyCursor = true;
basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
basicService.method = "POST";
basicService.resultFormat = "text";
basicService.url = url;
basicService.addEventListener(ResultEvent.RESULT, listener);
basicService.send();
}
private function httpFault(event:FaultEvent, component:String = null):void {
var faultstring:String = event.fault.faultString;
var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true);
dispatchEvent(eventObj);
trace(faultstring);
}
}
}
So to sum it all up:
- The event listener listens to the custom event dispatched by any custom component.
- The event listener does not listen to the custom event duspatched by an AS class.
Those who wonder, the event really gets dispatched, that's why I added a trace call.
The instance of Controller Class would have to be added to stage for that to work.
by doing
addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
in the main file you are adding the listener to the stage.
So basically you are doing.
stage.addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
If controler instance is not on stage you won't see the event.
You might want to look into a Singleton type pattern for your data management as that would fit this setup pretty good.
Main:
Controller.getLastInstance().addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true)
.
package components.dashboard
{
import components.dashboard.models.*;
/* Event imports */
import flash.events.*;
import main.events.*;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="showNotice", type="main.events.ShowNoticeEvent")]
public class Controller extends UIComponent
{
static public function getLastInstance():Controller { return _instance; }
static private var _instance:Controller;
private var baseUrl:String;
public function Controller(baseUrl:String)
{
_instance = this;
this.baseUrl = baseUrl;
}
public function getRunningQuotations():void
{
var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();
execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations");
}
public function getRecentProjects():void
{
var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();
execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
}
public function getLatestCustomers():void
{
var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();
execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
}
private function execService(url:String, listener:Function, component:String):void
{
var basicService:HTTPService = new HTTPService(baseUrl);
basicService.showBusyCursor = true;
basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
basicService.method = "POST";
basicService.resultFormat = "text";
basicService.url = url;
basicService.addEventListener(ResultEvent.RESULT, listener);
basicService.send();
}
private function httpFault(event:FaultEvent, component:String = null):void {
var faultstring:String = event.fault.faultString;
var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true);
dispatchEvent(eventObj);
trace(faultstring);
}
}
}
Not Ideal since you could only ever have 1 of them.
But I think better than having to turn a simple EventDispatcher into DisplayObject and add it to stage just to Simply bubble.

ActionScript - Access List/DataProvider From Custom CellRenderer

the code below sets up a List object in the main controller class that uses a custom cell renderer (CustomListCell class). the CustomListCell class creates a Button object for the cell that will be used to delete itself from the List's DataProvider.
how can i properly access the parent List object from its custom cell renderer?
//Controller Class
private function createList():void
{
provider = new DataProvider(data);
list = new List();
list.width = 200;
list.height = 400;
list.rowHeight = 50;
list.dataProvider = provider;
list.setStyle("cellRenderer", CustomListCell);
}
-----
//CustomListCell Class
import fl.controls.Button;
public class CustomListCell extends Sprite implements ICellRenderer
{
public function CustomListCell()
{
var button:Button = new Button();
button.label = "Delete Cell";
button.addEventListener(MouseEvent_MOUSE_DOWN, deleteCellHandler);
addChild(button);
}
private function deleteCellHandler(evt:MouseEvent):void
{
//Access List/DataProvider Here
}
//required implemented ICellRenderer functions follow
}
UPDATE
the following is my working custom renderer that implements ICellRenderer with Flash v3 List component. the List's dataProvider consists of 2 elements for each cell: randomColor and randomNumber.
package
{
//Imports
import fl.controls.Button;
import fl.controls.List;
import fl.controls.listClasses.ICellRenderer;
import fl.controls.listClasses.ListData;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.geom.ColorTransform;
//Class
public class TouchListRenderer extends Sprite implements ICellRenderer
{
//Properties
private var cellWidthProperty:Number;
private var cellHeightProperty:Number;
private var dataProperty:Object;
private var listDataProperty:ListData;
private var selectedProperty:Boolean;
//Cell Display Objects
private var backgroundCanvas:MySprite = new MySprite();
private var numberTextField:TextField = new TextField();
private var button:Button = new Button();
//Constructor
public function TouchListRenderer()
{
}
//Size Setter (Getter Functions Intentionally Omitted)
public function setSize(width:Number, height:Number):void
{
cellWidthProperty = width;
cellHeightProperty = height;
}
//Data Setter
public function set data(value:Object):void
{
dataProperty = value;
}
//Data Getter
public function get data():Object
{
return dataProperty;
}
//List Data Setter
public function set listData(value:ListData):void
{
listDataProperty = value;
}
//List Data Getter
public function get listData():ListData
{
return listDataProperty;
}
//Selected Setter
public function set selected(value:Boolean):void
{
selectedProperty = value;
layout();
}
//Selected Getter
public function get selected():Boolean
{
return selectedProperty;
}
//Size And Layout
private function layout():void
{
var newColor:ColorTransform = new ColorTransform();
newColor.color = dataProperty.randomColor;
backgroundCanvas.transform.colorTransform = newColor;
backgroundCanvas.scaleX = cellWidthProperty / backgroundCanvas.width;
backgroundCanvas.scaleY = cellHeightProperty / backgroundCanvas.height;
numberTextField.text = dataProperty.randomNumber;
numberTextField.autoSize = TextFieldAutoSize.LEFT;
numberTextField.textColor = 0xFFFFFF;
numberTextField.x = 50;
numberTextField.y = cellHeightProperty / 2 - numberTextField.height / 2;
numberTextField.border = true;
numberTextField.selectable = false;
button.label = "Delete";
button.x = cellWidthProperty - button.width - 50;
button.y = cellHeightProperty / 2 - button.height / 2;
button.drawNow();
button.addEventListener(MouseEvent.MOUSE_DOWN, buttonClickEventHandler);
addChild(backgroundCanvas);
addChild(numberTextField);
addChild(button);
}
//Button Click Event Handler
private function buttonClickEventHandler(evt:MouseEvent):void
{
List(listDataProperty.owner).removeItemAt(listDataProperty.index);
}
//Style Setter
public function setStyle(style:String, value:Object):void
{
}
//Mouse State Setter
public function setMouseState(state:String):void
{
}
}
}
package
{
import flash.display.Sprite;
public class MySprite extends Sprite
{
public function MySprite()
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0, 0, 10, 10);
graphics.endFill();
}
}
}
ugh! the answer was in front of me the whole time! next time remind me to check the docs:
List(listData.owner)
fl.controls.listClasses.ListData.owner
There are multiple ways to do this.
Here is a very hacky solution: Use an icon, and have that icon dispatch a close event.
The idea is you'll place a custom MovieClip in each list cell as icon. That icon will dispatch an event with the index of the cell clicked so you can remove it.
1st step: Make a basic custom event to pass cell index through:
package{
import flash.events.Event;
public class CloseEvent extends Event{
public static const CLOSE:String = 'close';
public var index:int;
public function CloseEvent(type:String,bubbles:Boolean = true,cancelable:Boolean=true){
super(type,bubbles,cancelable);
}
}
}
2nd step:: Draw a close icon or something, convert it to MovieClip and Export for Actionscript
3rd step: Add the event listener to dispatch the custom event when the close icon is clicked.
Inside the close icon Movie Clip I've placed the following actions:
import fl.controls.listClasses.CellRenderer;
//setup click
buttonMode = true;
if(parent) parent.mouseChildren = true;
addEventListener(MouseEvent.MOUSE_DOWN,dispatchClose);
//setup event
var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE,true);
if(parent) closeEvent.index = CellRenderer(parent).listData.index;
//listen to click and pass on
function dispatchClose(event:MouseEvent):void {
dispatchEvent(closeEvent);
}
Very basic stuff, listen for mouse down, create an event and set the index and dispatch that event on click. The icon is added to a cell renderer, therefor the cell render is it's parent which it has a listData property among others, which holds the index of the cell.
So here's how the test snippet looks:
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1),icon:Close});
ls.dataProvider = dp;
addEventListener(CloseEvent.CLOSE,deleteItem);
function deleteItem(event:CloseEvent):void {
ls.removeItemAt(event.index);
}
Since the CloseEvent bubbles, we can catch it from outside the cell renderer's icon and tell the list to remove the item at that index. It's possible to do that within the icon, but it will be necessary to 'climb' up the hierarchy all the way to the list, and it's pretty hacky already.
I did this because, I was probably as lazy as #TheDarkIn1978 :P to implement the ICellRenderer functions. Then I looked at question code again and didn't understand why the custom cell extends a Sprite, when CellRenderer already implements the ICellRenderer functions already.
So here is my attempt to do it in a less hacky manner:
package{
import fl.controls.*;
import fl.controls.listClasses.*;
import fl.data.*;
import flash.events.*;
public class SCListCell extends CellRenderer implements ICellRenderer{
protected var closeButton:Button;
protected var closeEvent:CloseEvent;
override protected function configUI():void {
super.configUI();
closeButton = new Button();
closeButton.label = 'x';
closeButton.buttonMode = true;
closeButton.setSize(30,20);
closeButton.drawNow();
closeButton.addEventListener(MouseEvent.CLICK,close);
addChild(closeButton);
closeEvent = new CloseEvent(CloseEvent.CLOSE);
}
private function close(event:MouseEvent):void{
closeEvent.index = listData.index;
dispatchEvent(closeEvent);
}
override protected function drawLayout():void{
mouseChildren = true;
closeButton.x = width-closeButton.width;
}
}
}
Used the same CloseEvent to pass the index, and the custom cell has direct access to the listData object to fetch the index, so the sample snippet looks like this:
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1)});
ls.dataProvider = dp;
addEventListener(CloseEvent.CLOSE,deleteItem);
function deleteItem(event:CloseEvent):void {
ls.removeItemAt(event.index);
}
ls.setStyle('cellRenderer',SCListCell);
So to answer your question:
how can i properly access the parent
List object from its custom cell
renderer?
You can use the listData property of the cell renderer.
You can if you want to, but it means going up a few levels:
package{
import fl.controls.*;
import fl.controls.listClasses.*;
import fl.data.*;
import flash.events.*;
public class SCListCell extends CellRenderer implements ICellRenderer{
protected var closeButton:Button;
override protected function configUI():void {
super.configUI();
closeButton = new Button();
closeButton.label = 'x';
closeButton.buttonMode = true;
closeButton.setSize(30,20);
closeButton.drawNow();
closeButton.addEventListener(MouseEvent.CLICK,close);
addChild(closeButton);
}
private function close(event:MouseEvent):void{
List(this.parent.parent.parent).removeItemAt(listData.index);
}
override protected function drawLayout():void{
mouseChildren = true;
closeButton.x = width-closeButton.width;
}
}
}
Which leaves the list creation part as simple as:
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1)});
ls.dataProvider = dp;
ls.setStyle('cellRenderer',SCListCell);
CloseEvent isn't needed in this case.
HTH