Last week we discussed a few ways that you can debug your widget from inside Captivate. This week I’ll show you how to trick your widget into believing it’s in Captivate while still testing in your IDE.
To Trick A Widget
In pretty much every post I’ve written so far, I’ve linked back to one of the first articles I ever wrote – the Template Methods post. I’ve linked back to it so often, that my blogging software now makes the link automatically when I type ‘Template Methods’ (It’s becoming sentient!), with good reason too.
Template Methods are the most essential feature in WidgetFactory. Without them, each Widget Mode would do the same thing and widgets would be pointless. With Template Methods employed, all your mode code is segregated nicely into individual methods to be called when needed.
Now don’t let the word ‘Template’ fool you into thinking there’s something special about these methods (or functions). They’re just the same as any other function in your program, and you can call them yourself just the same.
So what would happen if instead of Captivate calling the Template Method, we called it instead? Let’s say, in our constructor, like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package { import fl.controls.TextInput; import widgetfactory.StaticWidget; public class TestingWidget extends StaticWidget { private var textField:TextInput; public function TestingWidget() { ///////////// THE IMPORTANT BIT enterPropertiesDialog(); } override protected function enterPropertiesDialog():void { // Building the Properties Dialog interface. // Of sorts textField= new TextInput(); addChild(textField); textField.width = 250; textField.text = "Seriously... I'm a Properties Interface." // Centre text field. textField.x = stage.stageWidth / 2 - textField.width / 2; textField.y = stage.stageHeight / 2 - textField.height / 2; } } } |
Then when we publish the swf, we’d get…
This kicks the widget’s Properties Dialog code off even though it’s not inside Captivate at all. Which means you can test how your Properties Dialog interface is going to act, without having to leave your IDE. Which means you can use all your IDE’s debugging tools, including trace!
You can do this for any of the other widget modes as well, and it works remarkably well for the Widget Panel Preview (enterWidgetPanelPreview()), and even Stage mode (enterStage()). Where you start running into difficulties is with Runtime.
If your widget’s actions are relatively internal, then you could probably test it successfully in the IDE. However, if your widget interacts with the Captivate Movie at all, in say: grabbing slide objects, reading Captivate Variables, jumping to another slide, then the only way to reliably test it is to bring it into Captivate.
About now some of you may be raising your hands and asking: “What about Widget Properties?” Well that’s a good point. Both the Properties Dialog and Stage modes rely heavily on Widget Properties. Fortunately there is a way to get around that. Fake ‘em!
How to Forge Widget Properties
This is quite similar to The Widget King Widget Properties Method I wrote about in another post. I’ll try and sum up in a few sentences what it took me that whole post to explain.
The first time the user enters the Properties Dialog, there are no proir properties to populate the interface. In this case you have to set up some default properties. We have essentially the same problem here and can use the same method to solve it.
Let’s take the widget example above and make some changes. Let’s save and text written in the textField to a Widget Property.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package { import fl.controls.TextInput; import widgetfactory.StaticWidget; public class TestingWidget extends StaticWidget { private var textField:TextInput; public function TestingWidget() { ///////////// THE IMPORTANT BIT enterPropertiesDialog(); } override protected function enterPropertiesDialog():void { if (properties.text == undefined) { properties.text = "Default Text"; } // Building the Properties Dialog interface. // Of sorts textField = new TextInput(); addChild(textField); textField.width = 250; textField.text = properties.text; // Centre text field. textField.x = stage.stageWidth / 2 - textField.width / 2; textField.y = stage.stageHeight / 2 - textField.height / 2; } override protected function saveProperties():void { properties.text = textField.text; } } } |
To do that we’ve had to make a number of changes, but most important for us is this if statement:
1 2 3 | if (properties.text == undefined) { properties.text = "Default Text"; } |
This if statement checks if the Widget Properties had been set before. If they haven’t, then we give the property a default value which is then applied to the textfield latter. However, this if statement will evaluate to true when testing in your IDE also. So you’ll see the default text come up.
All fine and dandy, but what if you wanted to test a certain combination of properties without messing with your defaults? In that case set those properties up in your constructor before you call enterPropertiesDialog(). In that case the if statement will evaluate to false and wont set up the defaults.
1 2 3 4 5 | public function TestingWidget() { properties.text = "Not default text. HA-HA!"; enterPropertiesDialog(); } |
If you have a large set of properties though, it might be better to extract this operation into a function of its own. Then when you come to releasing your widget, you only have to comment out one line.
Bare in mind this method will work just as well with any of the other Widget Modes.
Faking Template Methods for Question Widgets
Question Widgets have some additional Template Methods. Most notably the submit() method, which is called when the audience submits the question, and the clearAnswers() method, which is called when the audience clicks the clear button.
But what if you’re testing your question in the IDE and you want to see if your submit process, or question clearing, is working correctly?
In that case, you can add a temporary button to the stage, listen for when it’s clicked, and when it is call the submit() or clearAnswers() template method. In code, it looks like this:
1 2 3 4 5 6 7 8 9 10 11 | var button:Button = new Button(); addChild(button); button.label = "Submit"; button.addEventListener(MouseEvent.CLICK, onButtonClick); private function onButtonClick(e:MouseEvent):void { submit(); } |
You could also jerry rig something like this to trigger the saveProperties() Template Method, and then trace out the properties object to see if your properties are being extracted correctly.
The other advantage of this method, besides being able to use the beloved trace, is that it saves a lot of time. Rather then having to pull your widget into Captivate every time you make a change, just publish the movie and there you go!
So in short: Call a Template Method and everyone’s happy!




