Dealing with the unfamiliar concept (to me) of asynchronous and event driven programming I struggle with the correct structure of my programs in AS3.
What I want to do is write a class which presents the user with a dialogue box with some text (sent to the constructor) and two buttons 'Yes' and 'No'. Thankfully this is no longer a problem to me. The problem comes in when deciding the correct structure of the program to get which button has been clicked.
Let's say I have Main.as which at some point calls new MyDialog, my theoretical dialogue class. I have a getter in MyDialog.as which sets up a variable myButton which is 0 by default, 1 if Yes is clicked and 2 if No is clicked.
Obviously I can't create a dialogue then immediately use the getter, the user won't have had time to click either button, they may take any amount of time to do so. As I see it I'd have to have a timer (or frame event) loop in Main.as which continually uses the getter to look at myButton then act accordingly when it changes.
This seems wrong to me. My Main.as would have to have lots of state flags for each dialogue I create. It would be messy and seems to go against the principles of event driven programming.
I realise I could have MyDialog just create the graphics and then in Main.as have an event triggered when the buttons in that dialogue are clicked but that seems to go against the encapsulation of Object Orientated Programming where MyDialog should be completely standalone.
So, are either of my possibilities the right way of doing it or have I overlooked something? Any thoughts on the matter would be gratefully received. I'm not the world's best coder and this newfangled stuff starts hurting my old head after a while :)
Just register the buttons to the functions you want them to call when clicked. You can pass them through the constructor like so...
package {
public class Modal extends Sprite {
public function Modal(message:String, yes:Function, no:Function) {
// Draw Background
graphics.beginFill(0xd9d9d9, 1);
graphics.drawRect(0, 0, 500, 300);
graphics.endFill();
// Create Text
var txt:TextField = new TextField();
txt.text = message;
addChild(txt);
// Create Yes Button
var btnYes = new Button();
addChild(btnYes)
btnYes.addEventListener("click", yes);
// Create No Button
var btnNo = new Button();
addChild(btnNo)
btnYes.addEventListener("click", no);
}
}
}
Mind that you'll need to import the appropriate classes, and you might be using an entirely different class for your buttons, but the gist remains. In fact, if you don't want to use event listeners on the remote functions, you could just pass arbitrary functions with custom arguments.
package {
private var funcYes:Function;
private var argsYes:Array;
private var funcNo:Function;
private var argsNo:Array;
public class Modal extends Sprite {
public function Modal(message:String, yes:Function, no:Function, yesArgs:Array = null, noArgs:Array = null) {
// Draw Background
graphics.beginFill(0xd9d9d9, 1);
graphics.drawRect(0, 0, 500, 300);
graphics.endFill();
// Create Text
var txt:TextField = new TextField();
txt.text = message;
addChild(txt);
// Create Yes Button
var btnYes = new Button();
btnYes.name = "yes";
addChild(btnYes)
btnYes.addEventListener("click", buttonListener);
// Create No Button
var btnNo = new Button();
btnNo.name = "no";
addChild(btnNo)
btnYes.addEventListener("click", buttonListener);
// Store functions and args for later use.
funcYes = yes;
argsYes = yesArgs;
funcNo = no;
argsNo = noArgs;
}
private function buttonListener(e:MouseEvent):void {
switch (e.currentTarget.name) {
case "yes":
if (argsYes != null) {
funcYes.apply(null, args);
} else {
funcYes();
}
case "no":
if (argsNo != null) {
funcNo.apply(null, args);
} else {
funcNo();
}
break;
}
}
}
}