Calling a function from one class, from another - actionscript-3

I'm having a slight issue with ActionScript 3 and I have come here to ask for some help.
I have two classes. One called Sledge and one called Sock, there is also the document class called Main.
My issues are as follows:
Inside of Sledge, I call a function that is defined inside of the Main document class. How would I go about telling the class to go to the document class and run that function? Would this also be the same for other classes or just for the document class?
Inside Sledge, I have the following statement: if(hitTestObject(sock.myHitArea)) { /* somecode*/ }
sock is an instance of another seperate class, and by this point has already been created. However when I try and run this I am told it is not defined. How would i go about solving this?

There's some ambiguity issues with how you expressed your question. It would help if you posted a short form of the code for the problem.
However, I'll try to answer the first question:
Inside of Sledge, I call a function that is defined inside of the Main document class. How would I go about telling the class to go to the document class and run that function?
You would want to pass the Main class to the Sledge class or use events which is preferable. If pass the class it will look like this...
class Sledge {
private var main:Main;
function Sledge(main:Main) {
this.main = main;
}
function doSomething():void {
main.runSomeFunction();
}
}
Or if using events:
class Main {
private var sledge:Sledge;
function Main() {
sledge = new Sledge();
sledge.addEventListener("mainDoSomething", doSomething);
}
private function doSomething(e:Event):void {
// .... do stuff
}
}
class Sledge extends EventDispacter {
function Sledge() {
}
public function doSomething():void {
dispatchEvent(new Event("mainDoSomething"));
}
}

Related

linking fla files together in actionscript using document classes

I am working in actionscript3, and since I'm self-taught, I think I've developed some bad habits, including coding on the timeline and using multiple scenes.
I am hoping to rectify this now that I'm working on a larger project.
Based on what I've read, linking multiple .fla files together is a better practice, each with their own document class. Is that correct?
If so, how do I load one .fla with its document class and then link that into the subsequent .fla file (instead of using scenes)? Or am I misinterpreting what was recommended?
Thanks!
There's no point to split your application in several loadable modules unless you have any of the following preconditions:
you have smart resource management to load and unload content
if you put everything into one file it gets just too big and hard to work with in design time or it takes far too long to compile
Regular AS3 alternative to working with scenes is creating/destroying content instances and using the main document class as their manager. You design content in the library and create behavior AS3 classes for them. Lets say, you have two content classes A and B. At the start the manager should show one of them and wait for the signal to show next one:
private var APage:A;
private var BPage:B;
gotoA();
function gotoA():void
{
if (BPage)
{
BPage.destroy();
removeChild(BPage);
BPage.removeEventListener(Event.CLOSE, gotoA);
}
APage = new A;
APage.addEventListener(Event.CLOSE, gotoB);
addChild(APage);
}
function gotoB():void
{
if (APage)
{
APage.destroy();
removeChild(APage);
APage.removeEventListener(Event.CLOSE, gotoB);
}
BPage = new B;
BPage.addEventListener(Event.CLOSE, gotoA);
addChild(BPage);
}
So, both A and B should have respective methods .destroy() that release used resources, unsubscribes methods from events, remove display objects, and so on, and they both should fire Event.CLOSE when they're done.
If you have many pages like that, you need to go for more algorithmic approach. For example, to create class BasicPage which will interact with manager and have the methods needed in all pages already declared:
package
{
import flash.display.Sprite;
class BasicPage extends Sprite
{
// A reference to the page manager instance.
public var Manager:PageManager;
public function destroy():void
{
while (numChildren > 0) removeChildAt(0);
Manager = null;
}
// Subclasses will have an access to this method to tell manager to show another page.
protected function showOtherPage(pageClass:Class):void
{
Manager.showPage(pageClass);
}
// A method that is called by manager when everything is ready.
// If page should take any actions on start it is a good idea to override this method.
public function startEngine():void
{
}
}
}
Then, example page A:
package
{
import flash.events.MouseEvent;
public class A extends BasicPage
{
// Lets say, class A in library have a designed button named Click.
public var Click:SimpleButton;
// We have things to undo here.
override public function destroy():void
{
Click.removeEventListener(MouseEvent.CLICK, onClick);
Click = null;
// Pass the destruction to superclass so it wraps its existence either.
super.destroy();
}
override public function startEngine():void
{
Click.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void
{
// Lets use inherited method to show other page.
showOtherPage(B);
}
}
}
So, PageManager will be like:
package
{
public class PageManager extends Sprite
{
private var Page:BasicPage;
// constructor
function PageManager()
{
super();
showPage(A);
}
function showPage(pageClass:Class):void
{
if (Page)
{
Page.destroy();
removeChild(Page);
Page = null;
}
Page = new pageClass;
Page.Manager = this;
addChild(Page);
Page.startEngine();
}
}
}
This all could look scary at first, but it really isn't. PageManager will always have a current page, once there's a need to show another page, the current will be destroyed on a regular basis. Each page class will tend to its own content, which makes coding simpler, for you don't need to see the whole picture. If you need any persistent data, keep it in the PageManager so each page will have access to the data with no need for the pages to communicate with each other.

Adobe/Apache Flex: Modify View in an ActionScript class

I have a WindowedApplication in Apache/Adobe Flex 4 which currently consists of one view (the view defined in the WindowedApplication MXML).
In that application I have an object which listens to data coming from a network. When data is available a method is called on that object and it shall update my view by changing the text of a label.
I do not have a reference to the view in the network listener object though. How can I get it?
This is part of my MXML where I define my view.
<fx:Script source="./ViewCodeBehind.as"/>
<!-- ommited stuff -->
<s:Label id="errorLabel"
text=""
fontSize="14"/>
<!-- Stuff in between -->
<s:Button label="Get Status"
click="getStatus();"/>
The code which is called when the button is clicked:
public function getStatus(): void
{
var networkGateway: NetworkGateway = new NetworkGatewayImpl();
networkGateway.getConnectionStatus();
}
And the NetworkGatewayImpl
public class NetworkGatewayImpl implements NetworkGateway
{
public function NetworkGatewayImpl()
{
}
public function getConnectionStatus(): void
{
// Start asynchronous network call
// when error occurs onNetworkError() is called
}
private function onNetworkError(): void
{
// Set "errorLabel" here: How?
}
}
Essentially I want to know some ways to update "errorLabel" from the NetworkGatewayImpl.
Based on your code, there could be multiple ways to solve this. Easiest way (as per me) would be to dispatch an event from the NetworkGatewayImpl class and listen to it on the instance you have created in the view class. So sample code would look like this:
public function getStatus(): void
{
var networkGateway: NetworkGateway = new NetworkGatewayImpl();
networkGateway.addEventListener("networkError", onNetworkError);
networkGateway.getConnectionStatus();
}
private function onNetworkError(e:Event):void
{
networkGateway.removeEventListener("networkError", onNetworkError);
this.errorLabel.text = "Your Text Here";
}
Dispatch your event like this from your NetworkGatewayImpl class:
private function onNetworkError(): void
{
this.dispatchEvent("networkError");
}
You will have to ensure that your NetworkGatewayImpl also implements the IEventDispatcher interface to be able to dispatch events.
Also, best practice would be to create a custom Event class (extending the Event class) and use constants instead of the literal 'networkError'
Hope this helps.

eventDispatcher from a sub class to another class

I have been struggling with the following for a couple of hours now, how do you call a custom class from another class if you do not extend that class for example.
I have on my main Base class a timer event, Base.myTimer.addEventListener(TimerEvent.TIMER, processTime) - Base class
Then I remove the method later in the code Base.mytimer.removeEventListener(TimerEvent.TIMER, processTime. - Base class
I have a button (Btn class) that when its done processing I want to call that method again, but I can't get it to work because the method does not exist in the button class but on the Base class so flash obviously gives me the error processTime is not defined.
For example now I want to re-instantiate the event listener from within the button, so I have
Base.myTimer.addEventListener(TimerEvent.TIMER, processTime);
or this.parent.parent["myTimer"].addEventListener()
myTimer is a static Timer in Base class.
I can make a normal dispatchEvent if its not a custom method for example Base.myTimer.dispatchEvent(new TimerEvent(TimerEvent.TIMER)).
The examples I have seen so far have not resolved my issue. Any help would be appreciated.
Looks like the button class is part of the child tree of the Base class. In this case, you can just do a dispatchEvent from the button class when it is clicked
dispatchEvent(new Event("AddListenerAgain", true));
In the Base class, you must be having access to the button class already, hence you can say:
button.addEventListener("AddListenerAgain", addListener);
Then in the Base class
private function addListener(e:Event) : void {
myTimer.addEventListener(TimerEvent.TIMER, processTime);
}
In this example, I have dispatched and listened for raw strings. This is not a recommended practice. You must read on how to dispatch custom events to do it correctly.
You could pass a reference to an instance of Base class into your Button instance.
// Button class
package {
import Base;
// Other imports...
public class Button {
public function Button(base:Base):void {
// processTime and myTimer must be public.
// I put this line in the constructor for brevity, but if you stored base
// in an instance variable, you could put this anywhere in the button
// class.
Base.myTimer.addEventListener(TimerEvent.TIMER, base.processTime)
}
}
}
// Create button like this.
var button:Button = new Button(base);
// Or if button is created inside of Base
var button:Button = new Button(this);
Even better would be to create two methods in the Base class, for adding and removing the listeners, and make myTimer and processTime private:
public class Base {
public function addTimerListeners():void {
myTimer.addEventListener(TimerEvent.TIMER, processTime)
}
public function removeTimerListeners():void {
myTimer.removeEventListener(TimerEvent.TIMER, processTime)
}
}
Then you can call these two methods from outside of the class. This keeps the inner workings of your class more hidden. If you decided you wanted to change myTimer to a instance variable instead of static, you wouldn't have to make any changes to code outside of your Base class. This is called encapsulation and is a good practice.

AS3 - Defining functions inside of other functions

When adding event listeners and defining their corresponding functions I find myself defining the function in the code of a constructor a lot. Something like this:
package
{
public class stuff extends Sprite
{
public function stuff()
{
minimizeBtn.addEventListener(MouseEvent.CLICK, minimizeOnClick);
function minimizeOnClick(e:MouseEvent):void
{
//do minimization stuff here
}
}
}
}
However, there is clearly another option to define it like any other method of the class. Something like this:
package
{
public class stuff extends Sprite
{
public function stuff()
{
minimizeBtn.addEventListener(MouseEvent.CLICK, minimizeOnClick);
}
internal function minimizeOnClick(e:MouseEvent):void
{
//do minimization stuff here
}
}
}
The second option may not really make sense because the function isn't really a method of the class. But my concern is that the first method will use up extra memory for each instance of the class. Which is the most efficient and correct way to do this and also does the first method take up extra memory or CPU time for each instance of the class?
Thanks!
The latter example is the correct way, and it's true that you should try encapsulate your addEventListener() and listening function within the relevant class. In your case, you may want to consider making a class for your minimizeBtn:
public class MinimizeButton extends SimpleButton
{
public function MinimizeButton()
{
addEventListener(MouseEvent.CLICK, _onClick);
}
private function _onClick(e:MouseEvent):void
{
// do minimization stuff here
}
}
MinimizeButton's _onClick() should then target the relevant instance of your class stuff and run whatever stuff needs to do from there.
This example's process is more like:
MinimizeButton: "I've been clicked, I should inform stuff so it can do something relevant."
Rather than:
stuff: "I'm going to sit and wait for MinimizeButton to get clicked, then I'll do what's required."

Border container create generic mouseOver function

I try to create a function to change border property of border container.
To do that I create a function for each border container on my MXML.
But I'd to code better and to do a generic function.
Today my function is:
protected function bcContact_mouseOverHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
bcContact.setStyle("borderVisible",true);
bcContact.setStyle("borderWeight",2);
bcContact.setStyle("borderColor",'#000099');
}
bcContact is one border container Id.
I try to replace bcContact by this but it doesn't work.
Can you help me to solve this beginner mistake.
Thanks
U can use event.CurrentTraget and then use the compare functions, compare with ids and do the settings.
You could extend the BorderContainer class (in Flash Builder, put in BorderContainer in the "Super class" text field)
Your class will look something like this:
import flash.events.MouseEvent;
import spark.components.BorderContainer;
package com.extensions.containers {
class MyBorderContainer {
function MyBorderContainer() {
this.addEventListener(MouseEvent.MOUSE_OVER, changeStyle);
this.addEventListener(MouseEvent.MOUSE_OUT, undoStyle);
}
private function changeStyle(e:MouseEvent):void {
this.setStyle("borderVisible",true);
this.setStyle("borderWeight",2);
this.setStyle("borderColor",'#000099');
}
private function undoStyle(e:MouseEvent):void {
this.setStyle("borderVisible",false);
this.setStyle("borderWeight",0);
this.setStyle("borderColor",'#000000');
}
}
}
This class will need to be in the file src/com/extensions/containers/MyBorderContainer.as
Then use this in your mxml as
<containers:MyBorderContainer>
</containers:MyBorderContainer>
where the namespace containers is set to point to com/extensions/containers