Flex Mobile - Custom Spark List ItemRenderer - actionscript-3

I am looking for some guidance to create a custom Spark List ItemRenderer for an Flex Mobile application I am developing.
Overview: Section List where each item has a checkbox control, Label, button control 1 - opens an accordion list below the item, button control 2 - opens Camera UI.
What I am struggling with is creating an itemrenderer that allows the accoridion list to be visible and be populated.
Update: Here's my existing code
<fx:Metadata>
[Event(name="checkBoxIconItemRendererChanged", type="flash.events.Event")]
[Event(name="cameraIconItemRendererChanged", type="flash.events.Event")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import spark.components.Label;
import spark.components.CheckBox;
import spark.components.HGroup;
import spark.components.Image;
import spark.layouts.HorizontalAlign;
import flashx.textLayout.formats.VerticalAlign;
//camera stuff
public var cameraIcon:Image;
public var friendsIcon:Image;
//checkbox stuff start
public var checkBox:CheckBox;
private var checkBoxChanged:Boolean;
private var _checkBoxField:String;
private var _checkBoxFunction:Function;
//list item group
public var listGroup:HGroup;
private var dataSource:IDataInput;
public function get checkBoxFunction():Function{
return _checkBoxFunction;
}
public function get checkBoxField():String{
return _checkBoxField;
}
public function set checkBoxFunction(value:Function):void{
if(_checkBoxFunction==value){
return;
}
_checkBoxFunction=value;
checkBoxChanged=true;
invalidateProperties();
}
public function set checkBoxField(value:String):void{
if(_checkBoxField==value){
return;
}
checkBoxChanged=true;
_checkBoxField=value;
invalidateProperties();
}
/*override public function set data(value:Object):void
{
checkBoxChanged=true;
super.data = value; //->invalidateProperties();
}*/
override protected function createChildren():void
{
super.createChildren();
listGroup = new HGroup();
var testLabel:Label = new Label();
testLabel.text = "Test Item";
listGroup.addElement(testLabel);
//listGroup.addChild(testLabel);
listGroup.visible = false;
listGroup.includeInLayout = false;
addChild(listGroup);
checkBox = new CheckBox();
//checkBox.skin = skins.ChallengeCheckBox; //throws error in the Skin
checkBox.width=64;//32
checkBox.height=64;//32
checkBox.scaleY=1;//.5
checkBox.scaleX=1;//.5
addChild(checkBox);
//listGroup.addChild(checkBox);
checkBox.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void{
dispatchEvent(new Event("checkBoxIconItemRendererChanged"));
});
friendsIcon = new Image();
friendsIcon.source = "assets/controls/eye_lightgray.png";
friendsIcon.verticalAlign = VerticalAlign.MIDDLE;
//cameraIcon.horizontalAlign = HorizontalAlign.RIGHT;
friendsIcon.width = 85;
friendsIcon.height = 85;
//cameraIcon.x = 275;
friendsIcon.x = Capabilities.screenResolutionX - 205;
friendsIcon.buttonMode = true;
friendsIcon.addEventListener(MouseEvent.CLICK,showFriends);
addChild(friendsIcon);
//listGroup.addChild(friendsIcon);
cameraIcon = new Image();
cameraIcon.source = "assets/controls/uncheckedbox.png";
friendsIcon.verticalAlign = VerticalAlign.MIDDLE;
//cameraIcon.horizontalAlign = HorizontalAlign.RIGHT;
cameraIcon.width = 85;
cameraIcon.height = 85;
//cameraIcon.x = 275;
cameraIcon.x = Capabilities.screenResolutionX - 105;
cameraIcon.buttonMode = true;
cameraIcon.addEventListener(MouseEvent.CLICK,launchCameraUI);
addChild(cameraIcon);
}
override protected function measure():void
{
super.measure();
measuredWidth+=getStyle("horizontalGap")+checkBox.width*checkBox.scaleY;
measuredHeight=Math.max(measuredHeight, checkBox.height*checkBox.scaleY);
}
override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
{
var paddingLeft:Number = getStyle("paddingLeft");
var paddingRight:Number = getStyle("paddingRight");
var paddingTop:Number = getStyle("paddingTop");
var paddingBottom:Number = getStyle("paddingBottom");
var horizontalGap:Number = getStyle("horizontalGap");
var verticalAlign:String = getStyle("verticalAlign");
setStyle("paddingLeft",paddingLeft+checkBox.width*checkBox.scaleX+horizontalGap);
super.layoutContents(unscaledWidth, unscaledHeight);
setStyle("paddingLeft",paddingLeft);
var vAlign:Number;
if (verticalAlign == "top")
vAlign = 0;
else if (verticalAlign == "bottom")
vAlign = 1;
else // if (verticalAlign == "middle")
vAlign = 0.5;
var viewHeight:Number = unscaledHeight - paddingTop - paddingBottom;
var checkBoxDisplayY:Number = Math.round(vAlign * (viewHeight - checkBox.height*checkBox.scaleY)) + paddingTop;
checkBox.x=paddingLeft;
checkBox.y=checkBoxDisplayY;
}
override protected function commitProperties():void
{
super.commitProperties();
if(checkBoxChanged){
checkBoxChanged=false;
if (checkBoxFunction != null)
{
checkBox.selected=checkBoxFunction(data);
}
else if (checkBoxField)
{
try
{
if (checkBoxField in data && data[checkBoxField] != null)
checkBox.selected=data[checkBoxField];
}
catch(e:Error)
{
trace(e.message);
}
}
}
}
//end
private var _backgroundSection:Number = 0xDDDDDD; //this is a grey
public function set backgroundSection(value:Number):void {
_backgroundSection = value;
}
private var _normalLabelField:String = "kick";
public function get normalLabelField():String {
return _normalLabelField;
}
public function set normalLabelField(value:String):void {
_normalLabelField = value;
}
private var _sectionField:String = "points";
public function get sectionField():String {
return _sectionField;
}
public function set sectionField(value:String):void {
if (value == _sectionField)
return;
_sectionField = value;
invalidateProperties();
}
/**
* Change the style based on the data: section item or regular item
*/
override public function set data(value:Object):void {
//checkbox
checkBoxChanged=true;
if (value[_sectionField]) {
labelField = _sectionField;
labelDisplay.setStyle("textAlign", "center");
labelDisplay.setStyle("fontWeight", "bold");
} else {
labelField = _normalLabelField;
labelDisplay.setStyle("textAlign", "left");
labelDisplay.setStyle("fontWeight", "normal");
//labelDisplay.width = 300;
//labelDisplay.wordWrap = true;
//labelDisplay.multiline = true;
}
super.data = value;
}
override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void {
super.drawBackground(unscaledWidth, unscaledHeight);
//change the background if we render for a section title item
if (data[_sectionField]) {
graphics.beginFill(_backgroundSection, 1);
graphics.lineStyle();
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
//adding .parent to each, adding listGroup as parent reference
/*if (checkBox.parent.parent != null)
listGroup.removeChild(checkBox);
if (friendsIcon.parent.parent != null)
listGroup.removeChild(friendsIcon);*/
if (checkBox.parent != null)
removeChild(checkBox);
if (friendsIcon.parent != null)
removeChild(friendsIcon);
if (cameraIcon.parent != null)
removeChild(cameraIcon);
}
}
protected function launchCameraUI(event:MouseEvent):void
{
var cUI:CameraRoll = new CameraRoll();
if( CameraRoll.supportsBrowseForImage )
{
cUI.addEventListener( MediaEvent.SELECT, imageSelected );
cUI.addEventListener( Event.CANCEL, browseCanceled );
cUI.addEventListener( ErrorEvent.ERROR, mediaError );
cUI.browseForImage();
}
else
{
trace( "Image browsing is not supported on this device.");
}
}
protected function imageSelected(event:MediaEvent):void
{
trace( "Media selected..." );
var imagePromise:MediaPromise = event.data;
dataSource = imagePromise.open();
if( imagePromise.isAsync )
{
trace( "Asynchronous media promise." );
var eventSource:IEventDispatcher = dataSource as IEventDispatcher;
eventSource.addEventListener( Event.COMPLETE, onMediaLoaded );
}
else
{
trace( "Synchronous media promise." );
readMediaData();
}
}
protected function browseCanceled(event:Event):void
{
// TODO Auto-generated method stub
}
protected function mediaError(event:ErrorEvent):void
{
// TODO Auto-generated method stub
}
private function onMediaLoaded( event:Event ):void
{
trace("Media load complete");
readMediaData();
}
private function readMediaData():void
{
//do something with the data
}
protected function showFriends(event:MouseEvent):void
{
// TODO Auto-generated method stub
if (listGroup.visible == true)
{
listGroup.visible = false;
listGroup.includeInLayout = false;
trace("Hide Friends Drop Down");
}
else
{
listGroup.visible = true;
listGroup.includeInLayout = true;
trace("Show Friends Drop Down");
}
}
]]>
</fx:Script>
Im using the following as the base code: http://corlan.org/2011/07/04/creating-flex-mobile-section-lists/
UPDATE: Ultimately I would like to create the following layout where the checkbox is independent of the list item & when you touch the eye icon it opens an accordian style list:

Related

How do I access a method of ClassA from classB?

I didn't really know what exactly to ask in the question. So I am going to explain everything here:
I am working on a Desktop AIR Database Application I have a Class named "Database Screen" which is linked to a movie clip:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.InteractiveObject;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filesystem.FileMode;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.TextField;
public class DatabaseScreen extends MovieClip {
private var allButtons:Array;
private var codeSelected:Boolean;
private var nameSelected:Boolean;
private var xmlDatabase:XML;
private var dbFile:File;
public var xmlList:XMLList;
private var totalProducts:uint;
private var totalItems:uint = 0;
private var productExists:Boolean;
private var productId:Number;
private var XMLReader:xmlReader;
public function DatabaseScreen() {
allButtons = [searchPanel.search_btn, addNewPanel.addNew_btn, dbStatsPanel.xls_btn, searchPanel.code_radio, searchPanel.name_radio];
init();
}
private function init():void
{
XMLReader = new xmlReader();
//adding event listeners..
for(var i:int = 0; i<allButtons.length; i++)
{
allButtons[i].addEventListener(MouseEvent.MOUSE_OVER, onOver, false, 0, true);
allButtons[i].addEventListener(MouseEvent.MOUSE_OUT, onOut, false, 0, true);
allButtons[i].addEventListener(MouseEvent.MOUSE_DOWN, onDown, false, 0, true);
allButtons[i].addEventListener(MouseEvent.MOUSE_UP, onUp, false, 0, true);
allButtons[i].addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
allButtons[i].buttonMode = true;
}
//creating a new file for the database
dbFile = File.documentsDirectory.resolvePath("BlackCat/Database.xml");
xmlDatabase = new XML();
getXML();
saveXML();
getTotalItems();
dbStatsPanel.items.text = String(totalItems);
}
private function getXML():void
{
if(dbFile.exists)
{
var stream:FileStream = new FileStream();
stream.open(dbFile, FileMode.READ);
xmlDatabase = new XML(stream.readUTFBytes(stream.bytesAvailable));
stream.close();
xmlList = xmlDatabase.Product;
dbStatsPanel.products.text = xmlList.length();
XMLReader.xmlData = xmlList;
XMLReader.updateXMLList(xmlList);
}
else
{
xmlDatabase = <Products></Products>
}
}
public function getXMlList():XMLList
{
return xmlList;
}
private function getTotalItems():void
{
for(var i:int = 0; i < xmlList.length(); i++)
{
totalItems += uint(xmlList[i].#Qty);
}
}
private function saveXML():void
{
var stream:FileStream = new FileStream();
stream.open(dbFile, FileMode.WRITE);
stream.writeUTFBytes(xmlDatabase.toXMLString());
}
private function onDown(evt:MouseEvent):void
{
evt.target.scaleX = evt.target.scaleY = .8;
}
private function onUp(evt:MouseEvent):void
{
evt.target.scaleX = evt.target.scaleY = 1;
}
private function onOver(evt:MouseEvent):void
{
evt.target.alpha = .5;
}
private function onOut(evt:MouseEvent):void
{
evt.target.alpha = 1;
evt.target.scaleX = evt.target.scaleY = 1;
}
private function onClick(evt:MouseEvent):void
{
switch(evt.target.name)
{
case "code_radio":
codeSelected = true;
nameSelected = false;
searchPanel.code_radio.gotoAndStop(1);
searchPanel.name_radio.gotoAndStop(2);
break;
case "name_radio":
nameSelected = true;
codeSelected = false;
searchPanel.code_radio.gotoAndStop(2);
searchPanel.name_radio.gotoAndStop(1);
break;
case "addNew_btn":
//Checking if the product already exists..
for(var i:int = 0; i < xmlList.length(); i++)
{
if(xmlList[i].#code == addNewPanel.add_code_txt.text)
{
productExists = true;
productId = i;
}
}
if(productExists)
{
var PQty:uint = uint(xmlList[productId].#Qty);
var PQtoAdd:uint = uint(addNewPanel.add_qty_txt.text);
PQty += PQtoAdd;
xmlList[productId].#Qty = String(PQty);
productExists = false;
}
else
{
xmlDatabase.appendChild(<Product code={addNewPanel.add_code_txt.text}
name={addNewPanel.add_name_txt.text} Price={addNewPanel.add_price_txt.text}
Qty={addNewPanel.add_qty_txt.text}></Product>);
}
totalItems += uint(addNewPanel.add_qty_txt.text);
xmlList = xmlDatabase.Product;
dbStatsPanel.products.text = xmlList.length();
dbStatsPanel.items.text = String(totalItems);
XMLReader.updateXMLList(xmlList);
saveXML();
trace(xmlDatabase);
break;
}
}
public function setVisiblity(visibility:Boolean):void
{
switch(visibility)
{
case true:
this.visible = true;
break;
case false:
this.visible = false;
break;
}
}
public function getXMLList():XMLList
{
return xmlList;
}
}
}
And I have another class named "NewOrder", in this class I am trying to access the xmlList from the "DatabaseScreen" class but I am unable to do so.
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import com.greensock.TweenMax;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filesystem.FileMode;
public class NewOrder extends MovieClip {
private var allButtons:Array;
private var shoppingCart:Array;
private var scroller:FlickScroll;
private var db:DatabaseScreen;
private var XMLReader:xmlReader;
public function NewOrder() {
this.visible = false;
init(db);
}
private function init(dbase:DatabaseScreen):void
{
XMLReader = new xmlReader();
trace(XMLReader.xmlData);
scroller = new FlickScroll(masker, container, 84.05, -500);
addChild(scroller);
allButtons = [scan_btn, print_invoice];
shoppingCart = [];
for(var i:int = 0; i < allButtons.length; i++)
{
allButtons[i].addEventListener(MouseEvent.MOUSE_OVER, onOver, false, 0, true);
allButtons[i].addEventListener(MouseEvent.MOUSE_OUT, onOut, false, 0, true);
allButtons[i].addEventListener(MouseEvent.MOUSE_DOWN, onDown, false, 0, true);
allButtons[i].addEventListener(MouseEvent.MOUSE_UP, onUp, false, 0, true);
allButtons[i].mouseChildren = false;
allButtons[i].buttonMode = true;
}
}
private function onOver(evt:MouseEvent):void
{
evt.target.alpha = .5;
}
private function onOut(evt:MouseEvent):void
{
evt.target.alpha = 1;
evt.target.scaleX = evt.target.scaleY = 1;
}
private function onDown(evt:MouseEvent):void
{
evt.target.scaleX = evt.target.scaleY = .8;
}
private function onUp(evt:MouseEvent):void
{
evt.target.scaleX = evt.target.scaleY = 1;
if(evt.target.name == "scan_btn")
{
var cartElement:CartElement = new CartElement();
container.addChild(cartElement);
cartElement.x = 0;
cartElement.alpha = 0;
TweenMax.to(cartElement, .4, {alpha:1});
shoppingCart.push(cartElement);
cartElement.id_txt.text = String(shoppingCart.length) + " - ";
if(shoppingCart.length < 2)
{
cartElement.y = container.height - 30;
}
else
{
cartElement.y = container.height + 5;
}
}
}
}
}
And there is a Main class in which I handle all the screens , e.g DatabaseScreen, NewOrder.. Which means I have added these to the display list in the Main class. To access the xmlList from the DatabaseScreen , I tried creating a new instance in the NewOrder class, but it creates to DatabaseScreen(s). I also tried creating another class named "xmlReader":
package {
public class xmlReader {
public var xmlData:XMLList;
public function xmlReader() {
}
public function updateXMLList(updatedList:XMLList):void
{
xmlData = updatedList;
}
}
}
In the databaseScreen class, as soon as I populate the xmlList , I set the xmlData of the xmlReader class equal to the xmlList from the databaseScreen class. And when I trace the XMLReader.xmlData in the databaseScreen , it works fine . But when I do the same thing in the NewOrder class, I get "null" in the output window.
How do I solve this problem. Any help is greatly appreciated.
You will need to pass a reference into the Order class to have access to the DatabaseScreen class. Something like this.
var ds = new DatabaseScreen();
var or = new NewOrder(ds)
Inside the NewOrder you can save the ref.
public class NewOrder {
private var screens:DatabaseScreens;
public function NewOrder(ds:DatabaseScreens) {
screens = ds;
// Now you can call screens.xmlList
}
}

Sprite movement basically right but

This is basically just drag and double click to set (so drag is temporarily disabled) but the sprite doesn't keep with the mouse- can someone point me to better code- otherwise I'll with go with this- so much more to do.
//The initial event performed when the button is first clicked;
internal var m_nDoubleClickSpeed:Number = 300;
internal var m_toMouse:Number;
internal var moveready:Boolean = false;
internal var initalx:uint;
internal var initialy:uint;
internal var move:Boolean;
internal function clickDoubleClick(e:MouseEvent):void {
if (isSet == false) {
this.startDrag();
}
if (isNaN(m_toMouse)==false) {
clearTimeout(m_toMouse);
HandleDoubleClick();
} else {
m_toMouse = setTimeout(HandleSingleClick, m_nDoubleClickSpeed);
}
}
internal function HandleSingleClick():void {
trace("HandleSingleClick");
trace("isSet");
trace(isSet);
this.stopDrag();
m_toMouse = NaN;
}
internal function HandleDoubleClick():void {
if (isSet == false) {
isSet = true;
this.stopDrag()
} else {
isSet = false;
}
trace("HandleDoubleClick");
m_toMouse = NaN;
}
internal function goodX(inX:Number):Number {
if (inX < 0) {
return 0;
}
if (inX > (stage.stageWidth) ) {
return (stage.stageWidth);
}
return inX;
}
internal function goodY(inY:Number):Number {
if (inY < 0) {
return 0;
}
if (inY > stage.stageHeight) {
return stage.stageHeight;
}
return inY;
}
I'm not sure if I understood you correctly. So you want to start drag on single click and drag until doubleclicked right? If so you can try something like that:
public class ClickAndDrag extends Sprite
{
private var clickTimeout:uint;
private var doubleClickSpeed:int = 500;
private var clickedOnce:Boolean;
private var mouseOnClick:Point;
private var isDragging:Boolean;
public function ClickAndDrag()
{
graphics.beginFill(Math.random()*0xffffff, 1);
graphics.drawCircle(0, 0, 20);
graphics.endFill();
this.buttonMode = true;
addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
}
private function handleMouseDown(e:MouseEvent):void
{
if (isDragging)
{
if (clickedOnce)
handleDoubleClicked();
else
{
//if it's not clicket within next doubleClickSpeed ms then doubleClickSpeed will be set to false;
clickedOnce = true;
clickTimeout = setTimeout( handleClickTimeout, doubleClickSpeed );
}
}
else
{
handleClickAndDrag();
}
}
//clicked once when dragging
private function handleClickOnce():void
{
graphics.clear();
graphics.beginFill(Math.random()*0xffffff, 1);
graphics.drawCircle(0, 0, 20);
graphics.endFill();
}
//clicked once when not dragging
private function handleClickAndDrag():void
{
isDragging = true;
this.addEventListener(Event.ENTER_FRAME, handleFrame);
mouseOnClick = new Point(this.mouseX, this.mouseY);
}
//doubleclicked when dragging
private function handleDoubleClicked():void
{
clearTimeout(clickTimeout);
clickedOnce = false;
this.removeEventListener(Event.ENTER_FRAME, handleFrame);
isDragging = false;
}
private function handleClickTimeout():void
{
clickedOnce = false;
handleClickOnce();
}
private function handleFrame(e:Event):void
{
this.x = stage.mouseX - mouseOnClick.x;
this.y = stage.mouseY - mouseOnClick.y;
}
}
It basically waits for mousedown and if it's already dragging it checks if you clicked once (changes color) ot twice (stops dragging). Or if it's not dragging yet then it starts dragging. You may also want to handle leaving the stage (Event.MOUSE_LEAVE).

Adding object to another sprite layer causes issues

Essentially, the spawning ships appear above the crosshair whereas I want it to be the other way around. I tried adding the crosshair to another layer but then clicking / 'shooting' the ships does nothing. Any ideas?
public class Main extends MovieClip {
public static var backgroundLayer:Sprite = new Sprite();
public static var gameLayer:Sprite = new Sprite();
public static var interfaceLayer:Sprite = new Sprite();
public static var menuLayer:Sprite = new Sprite();
public var mainMenu:menuMain = new menuMain();
public var intro:IntroSound = new IntroSound();
public var soundControl:SoundChannel = new SoundChannel();
public var crosshair:crosshair_mc;
static var enemyArray:Array = [];
private var enemyShipTimer:Timer;
private var enemyShipTimerMed:Timer;
private var enemyShipTimerSmall:Timer;
public function Main()
{
addMenuListeners();
addChild(gameLayer);
addChild(backgroundLayer);
addChild(interfaceLayer);
addChild(menuLayer);
menuLayer.addChild(mainMenu);
interfaceLayer.addChild(howtoPlay);
interfaceLayer.addChild(gameEnd);
interfaceLayer.addChild(gameAbout);
soundControl = intro.play(0, 100);
stage.addEventListener(Event.ENTER_FRAME, update);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
}
private function update(e:Event):void
{
for each (var enemy:EnemyShip in enemyArray)
{
enemy.update();
if (enemy.dead)
{
enemy.kill();
}
}
}
private function mouseDown(e:MouseEvent):void
{
if (e.target.name) {
switch (e.target.name) {
case "enemy_big":
updateScore(5);
e.target.parent.damage();
break;
case "enemy_medium":
updateScore(10);
e.target.parent.damage();
break;
case "enemy_small":
updateScore(15);
e.target.parent.damage();
break;
}
}
}
function addMenuListeners():void
{
//Code to add event listeners
}
public function startGame(e:Event)
{
removeMenuListeners();
soundControl.stop();
if (howtoPlay.parent == interfaceLayer)
{
interfaceLayer.removeChild(howtoPlay);
}
if (gameAbout.parent == interfaceLayer)
{
interfaceLayer.removeChild(gameAbout);
}
if (gameEnd.parent == interfaceLayer)
{
interfaceLayer.removeChild(gameEnd);
}
if (mainMenu.parent == menuLayer)
{
menuLayer.removeChild(mainMenu);
}
enemyShipTimer = new Timer(2000);
enemyShipTimer.addEventListener("timer", sendEnemy);
enemyShipTimer.start();
enemyShipTimerMed = new Timer(2500);
enemyShipTimerMed.addEventListener("timer", sendEnemyMed);
enemyShipTimerMed.start();
enemyShipTimerSmall = new Timer(2750);
enemyShipTimerSmall.addEventListener("timer", sendEnemySmall);
enemyShipTimerSmall.start();
crosshair = new crosshair_mc();
gameLayer.addChild(crosshair);
crosshair.mouseEnabled = crosshair.mouseChildren = false;
Mouse.hide();
gameLayer.addEventListener(Event.ENTER_FRAME, moveCursor);
resetScore();
}
function spawnEnemy(type:String, speed:Number) {
var enemy = new EnemyShip(type, speed);
enemyArray.push(enemy);
gameLayer.addChild(enemy);
return enemy;
}
function sendEnemy(e:TimerEvent):void
{
Timer(e.currentTarget).delay = (1+Math.random()*2)*1000;
spawnEnemy("big", Math.random() * 5 + 12);
}
function sendEnemyMed(e:TimerEvent):void
{
Timer(e.currentTarget).delay = (1+Math.random()*2)*1000;
spawnEnemy("medium", Math.random() * 7 + 14);
}
function sendEnemySmall(e:TimerEvent):void
{
Timer(e.currentTarget).delay = (1+Math.random()*2)*1000;
spawnEnemy("small", Math.random() * 9 + 16);
}
static function updateScore(points)
{
score += points;
scoreText.text = String(score);
scoreHeader.setTextFormat(scoreFormat);
scoreText.setTextFormat(scoreFormat);
}
static function resetScore()
{
score = 0;
scoreText.text = String(score);
scoreText.setTextFormat(scoreFormat);
}
static function removeEnemy(enemyShip:EnemyShip):void {
enemyArray.splice(enemyArray.indexOf(enemyShip), 1);
gameLayer.removeChild(enemyShip);
}
function moveCursor(event:Event)
{
crosshair.x=mouseX;
crosshair.y=mouseY;
}
}
}
I expect MouseDowns are intercepted by the parent layer. You have employed mouseEnabled=false for crosshair, now you should do that for its parent.
public static var crosshairLayer:Sprite=new Sprite();
public function Main() {
... // initialize everything first
addChild(gameLayer);
addChild(crosshairLayer);
crosshairLayer.mouseEnabled=false;
crosshairLayer.mouseChildren=false;
}
Then you add crosshair to crosshairLayer.

maxScrollV doesn't take into account html image size <img> for scrolling textfield

I am using Flash Pro CS6. I have built a scrolling textfield which is injected with htmltext through XML.
The problem I am having is the maxScrollV doesn't seem to take into account my images . I have tried to set the dimensions in the html <img src='assets/images/test.png' height='330' width='330' /> but this seems to throw out the wordwrap.
public class ScrollingTextField extends Sprite
{
private var myText:TextField;
private var myFormat:TextFormat;
private var bounds:Rectangle;
private var boundHeight:Number;
private var slider:SliderImage;
public function ScrollingTextField()
{
trace("ScrollingTextField added");
myText = new TextField();
myFormat = new TextFormat();
slider = new SliderImage();
myFormat.font = "Arial";
myFormat.color = 0x333333;
myFormat.size = 14;
addChild(myText);
myText.htmlText = "init";
myText.setTextFormat(myFormat);
myText.wordWrap = true;
myText.multiline = true;
myText.setTextFormat(myFormat);
myText.selectable = false;
this.addChild(slider);
slider.addEventListener(MouseEvent.MOUSE_DOWN, dragSlider);
addEventListener(Event.ENTER_FRAME, checkSlider);
}
private function dragSlider(evt:MouseEvent):void
{
slider.startDrag();
slider.removeEventListener(MouseEvent.MOUSE_DOWN, dragSlider);
slider.addEventListener(MouseEvent.MOUSE_UP, dropSlider);
addEventListener(MouseEvent.MOUSE_MOVE,moveSlider);
}
private function dropSlider(evt:MouseEvent):void
{
slider.stopDrag();
slider.removeEventListener(MouseEvent.MOUSE_UP, dropSlider);
slider.addEventListener(MouseEvent.MOUSE_DOWN, dragSlider);
removeEventListener(MouseEvent.MOUSE_MOVE,moveSlider);
}
private function moveSlider(evt:MouseEvent):void
{
evt.updateAfterEvent();
if (evt.buttonDown)
{
slider.startDrag(false,bounds);
}
else
{
slider.stopDrag();
}
}
private function checkSlider(evt:Event):void
{
myText.scrollV = ((slider.y - bounds.y)* (myText.maxScrollV)/boundHeight);
}
public function textToDisplay(txt:String):void
{
myText.htmlText = txt;
myText.setTextFormat(myFormat);
}
public function setDimensions(w:Number, h:Number):void
{
boundHeight = h - slider.height;
bounds = new Rectangle(w + 20,10,0,h - slider.height);
slider.x = w + 20;
slider.y = 10;
myText.width = w;
myText.height = h;
}
public function checkTextFieldSize():void
{
trace("numLines = " + myText.numLines);
trace("text height = " + myText.textHeight);
trace("height = " + myText.height);
if (myText.textHeight < myText.height)
{
slider.visible = false;
}
else
{
slider.visible = true;
}
}
}
}
Well, I ended up doing a cheap workaround. From scouring the net, it seems that .maxScrollV just doesn't like .htmltext. I'll take it to Adobe... in the meantime adding in <p> </p> to the html a load of times to act as the image space, seems to do the trick.

AS3 disable editable/selectable for textInput inside of a Datagrid

I am currently trying to disable the selectable / editable / or change the textInput to dynamic to get my desired result.
I've got a custom datagrid with dropdowns and text input areas. However, if there is no data in my Model # column, I do not want to allow for any entry in the corresponding PurchasePrice cell.
col1 = new DataGridColumn("Model");
col1.headerText = "Model #";
c2.consumables_dg.addColumn(col1);
col1.width = 60;
col1.editable = false;
col1.sortable = false;
col1.cellRenderer = AlternatingRowColors_editNum_PurchasePrice;
col1 = new DataGridColumn("PurchasePrice");
col1.headerText = "Purchase Price";
c2.consumables_dg.addColumn(col1);
col1.width = 60;
col1.editable = false;
col1.sortable = false;
col1.cellRenderer = AlternatingRowColors_editNum_PurchasePrice;
I've tried various items in the AlternatingRowColors_editNum_PurchasePrice, but nothing seems to work as of yet. Please Look at what I've tried in my else statement of the if(__enbaled)
package{
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import fl.controls.TextInput;
import flash.text.TextFieldType;
import flash.events.Event;
import fl.controls.listClasses.ListData;
import fl.controls.listClasses.ICellRenderer;
public class AlternatingRowColors_editNum_PurchasePrice extends TextInput implements ICellRenderer
{
protected var _data:Object;
protected var _listData:ListData;
protected var _selected:Boolean;
private var __enabled:Boolean = false;
public static var _stage;
public static var _alignment;
private var tf:TextFormat;
public function AlternatingRowColors_editNum_PurchasePrice()
{
tf = new TextFormat();
if(__enabled){
if(_alignment == 2){
tf.align = TextFormatAlign.RIGHT;
}else if(_alignment == 1){
tf.align = TextFormatAlign.CENTER;
}else{
tf.align = TextFormatAlign.LEFT;
}
restrict = "0-9.";
addEventListener(Event.CHANGE, textChange);
}else{
//this.selectable = false; // did not work
//textField.selectable = false; // did not work
//textField.type = dynamic; // did not work
//textField.type = TextFieldType.DYNAMIC; // did not work
//this.mouseEnabled = false; // did not work
//this.tabEnabled = false; // did not work
//textField.mouseEnabled = false; // did not work
//textField.tabEnabled = false; // did not work
//selectable = false; // did not work
//this.selectable = false; // did not work
//_enabled = false; // did not work
//-----------------------------------------------------------
// *** Corresponding Entry to enable was placed above ***
//-----------------------------------------------------------
}
super();
}
public function textChange(Event):void{
//trace(_data.Discount);
_data.PurchasePrice = text;
}
public function get data():Object
{
return _data;
}
public function set data(value:Object):void
{
_data = value;
text = value.PurchasePrice;
if(value.Model != "") __enabled = true;
if (value.id % 2 == 0) {
setStyle("upSkin", AlternateColor1 );
} else {
setStyle("upSkin", AlternateColor2 );
}
}
public function get listData():ListData
{
return _listData;
}
public function set listData(value:ListData):void
{
_listData = value;
}
public function get selected():Boolean
{
return _selected;
}
public function set selected(value:Boolean):void
{
_selected = value;
}
public function setMouseState(state:String):void
{
}
override protected function drawLayout():void
{
textField.setTextFormat(tf);
super.drawLayout();
}
}
}
Am I just approaching this the wrong way? Instead of trying to stop the mouse, tab, or convert the text field to dynamic, should I be attempting something else in order to get the desired result?
Thanks,
jc
The easiest approach is to change the TextField type itself and then change it's selectable property:
//disable input
tf.selectable = false;
tf.type = TextFieldType.DYNAMIC;
//enable input
tf.selectable = true;
tf.type = TextFieldType.INPUT;
Also don't forget to set the mouseEnabled & tabEnabled properties as appropriate/needed for your fields.
Be sure to import the TextFieldType at the top of your class / page / frame as:
import flash.text.TextFieldType;