I’m glad to see that people are enjoying WidgetFactory 5. There are a tonne of new features. However, not all features are created equal, and some of the more obscure ones are actually really powerful. So over the next five weeks I’ll be counting down my top 5 new features of WidgetFactory. I’ll be separating the wheat from the chaff! No wait… that makes the rest of the features sound lame. I’ll be separating the wheat from the slightly less cooler wheat.
So what’s #5? It’s a feature that works in both CP4 and CP5 – Template Methods!
Note: Some of these new features are fairly advanced. For these posts I’m assuming you know the basics of how to build a widget with WidgetFactory. Don’t worry if you don’t understand this stuff yet. I’ll be coming back with more posts on the basics soon.
(I’d like to thank Whyves for suggesting this feature. I was cautious at first, but now I can’t live without them
)
What do Template Methods allow you to do? A Template Method allows you to code your widget to react according to what Captivate needs it to do at that point in time. For example, when Captivate displays the widget on stage, it should show a preview of what it will look like in the published Captivate Movie. There’s a Template Method for that. What about when your widget is actually in the Captivate Movie and not only needs to LOOK the part, but ACT the part too? There’s a Template Method for that. For each different role the widget has to play, there is a corresponding Template Method. As you can imagine, this multi-role lifestyle must be incredibly demanding on widgets. They must feel like they have no identity of their own.
But you know, that’s life.
What is a Template Method? In WidgetFactory, Template Methods are functions (functions and methods are the same thing. Programmers use the word ‘method’ when we want to sound smart) inside the StaticWidget, InteractiveWidget, and QuestionWidget classes that are called when Captivate needs the widget to do something. For example: the enterStage() Template Method is called when Captivate needs the widget to display something for the Stage.
The official term for each of these locations that the widget finds itself in is ‘Mode’. So shown above is a widget in ‘Stage Mode’. To get the widget to do something in one of these modes, we add some code to that mode’s corresponding Template Method and POOF, a pie will be thrown at the Captivate Author when the widget is displayed on the stage.
But how do we use Template Methods? Answer: Be a rebel! Get your widget to say to the widget class it is extending: “Yo-daddy-o! I love what you’re doing and all, but your enterStage method is a joke. Now if I had my way, here’s what I’d do with it.” In ActionScript (or any other programming language that labels itself as ‘Object Oriented’) classes can override, or provide an alternative for, the functions in the class that they are extending. We can override the enterStage Template Method like so:
1 2 3 4 5 6 7 8 9 10 11 | package { import widgetfactory.StaticWidget; public class MyWidget extends StaticWidget { override protected function enterStage():void { // Your stage code here } } } |
Now, when the widget is displayed on stage, and the StaticWidget class goes to call the enterStage method, it will be diverted to our new and improved enterStage function! Any code that you write in the enterStage method will be executed at that time.
Just to let you know, not all Template Methods are to inform you that the widget is entering a Widget Mode. The saveProperties Template Method is called when Captivate needs to extract properties information from the widget. The clearAnswers Template Method for QuestionWidgets is called when the user clicks the CLEAR button on the Question Widget’s interface. The use of all Template Methods are exactly the same, regardless of their purpose.
Now some of you are probably raising your hands and saying: “Whoa dude! Didn’t we used to do all this stuff with WidgetEvents? What happened to them?” Don’t fret, the WidgetEvents are still there (though some have been renamed), if you’re more comfortable with events, then go ahead and use them instead.
Which one is more powerful? Template Methods, or WidgetEvents? I’m not going to go out on a limb here and say: Neither.
Then why did you add Template Methods to WidgetFactory? Well they’re quicker to code. Compare how much code it takes to use an event…
1 2 3 4 5 6 | addEventListener(WidgetEvent.ENTER_STAGE, onEnterStage); private function onEnterStage(event:WidgetEvent):void { } |
…as opposed to a Template Method.
1 2 3 4 | override protected function enterStage():void { } |
That’s a real timesaver. It also looks more magical.
AWED CLIENT: Hey, if that enterStage function isn’t called anywhere in your code, how come your widget works?
YOU: Magic.
Let’s wrap up with a widget that harnesses this feature. This widget displays a text field, and when each widget mode ticks around, it fills that text field with information about said widget mode:
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | package { import flash.text.TextField; import flash.text.TextFieldAutoSize import widgetfactory.StaticWidget; public class WidgetModeWidget extends StaticWidget { private var textField:TextField; public function WidgetModeWidget () { textField = new TextField(); // Create a new TextFiekd addChild(textField); // Display the TextField on the stage centerTextField(); // The textField will resize to our text according to its center textField.autoSize = TextFieldAutoSize.CENTER; textField.text = "No Widget Mode"; } private function centerTextField():void { // Center textField textField.x = stage.stageWidth / 2 - textField.width / 2; // Horizontal textField.y = stage.stageHeight / 2 - textField.height / 2; // Vertical } /* The window that opens up when you click the widget's 'Properties Dialog' button in CP5, * or the Widget Parameters Tab in CP4. */ override protected function enterPropertiesDialog():void { textField.text = "Properties Dialog Mode" + "\n" + "Template Method: enterPropertiesDialog()" + "\n" + "Widget Event: WidgetEvent.ENTER_PROPERTIES_DIALOG"; // The \n starts a new line in the text field. centerTextField(); } /* The preview window in the Widget Properties Dialog in CP4 * Not available in CP5 */ override protected function enterPropertiesDialogPreview():void { textField.text = "Properties Dialog Preview Mode" + "\n" + "Template Method: enterPropertiesDialogPreview()" + "\n" + "Widget Event: WidgetEvent.ENTER_PROPERTIES_PREVIEW_DIALOG"; centerTextField(); } /* When the widget appears in the output Captivate Movie * */ override protected function enterRuntime():void { textField.text = "Runtime Mode" + "\n" + "Template Method: enterRuntime()" + "\n" + "Widget Event: WidgetEvent.ENTER_RUNTIME"; centerTextField(); } /* When the widget is previewed on the Captivate Stage. * */ override protected function enterStage():void { textField.text = "Stage Mode" + "\n" + "Template Method: enterStage()" + "\n" + "Widget Event: WidgetEvent.ENTER_STAGE"; centerTextField(); } /* The preview of the widget that is shown in the Widget Panel. * */ override protected function enterWidgetPanelPreview():void { textField.text = "Widget Panel Preview Mode" + "\n" + "Template Method: enterWidgetPanelPreview()" + "\n" + "Widget Event: WidgetEvent.ENTER_WIDGET_PANEL_PREVIEW"; centerTextField(); } } } |
Click here to download the widget.
Happy Widgeting. (Would that word have two ‘t’s?)



I tried the widget, but I see no text in the stage mode.
B.t.w. I love your work! Currently i’m making the change from AS2 to AS3 and this is a good way for practising.
Thanks so far!
Hi Chris, glad you found this useful.
I also get that bug, but it’s weird. I’ve tested this out with some of my more complicated widgets, and they show up fine on the Captivate 5 stage. I’ll have to do some more testing…
Any progress on this? I see no text in the stage in CP5.5.
Hi Peno,
Are you by any chance positioning your text via stage.stageHeight or stage.stageWidth?
Hi Tristan,
Nice write up … I really like your writing style. It’s perfect to introduce concept to newcomers. Reminds me of the type of writing that can be founds in books from the “Head First” labs.
Also glad that you embraced the template methods. Told you that it was cool, didn’t I ;P
Whyves
Thanks Whyves,
We’ve got a Head First book on design patterns in our library. I’ve flicked through it a couple of times, (Trying to figure out what Factories were), but never really got into reading it. Rod often tells me that they’re good books.
I must investigate further!
Hey Tristan this is a great tutorial.
say I enterPropertiesDialog() and have a variable that i set how do i save the variables i set so when I view properties dialog they havent changed and when I published file the file out
just found the section in your doco on the save properties stuff thanks anyways
Hey Tristan I though maybe you could help me i’m trying to get an array of slideLabels for a project im working on any ideas on where to look
Hi JJ. Try looking under the slide’s slideXMl.AccProps.name, For example, if you wanted to access the widget’s slide’s slidelabel, you’d write the following:
widgetSlide.slideXMl.AccProps.name;
widgetSlide.parent holds all the slides in the project. If you can find a way of drilling into each of them and looking under their slideXMl.AccProps.name, you should be able to get your array. Just be sure to test with different types of slides, such as question slides, as these are named differently to regular slides.
You sir truly are the WIDGET KING!!!
hey Ive been experiencing errors while saving properties using the override protected function saveProperties():void
but everything works fine when i use the event widget I think there might be some bugs in the overide
What kind of errors are you getting?
I’m having a lot of problems with the saveProperties function I cant seem to bring the variables through in runtime. they dominantly save as the options i set in the enterPropertiesDialog repopulates.. any advice would be more than welcome
What kind of objects are you trying to save as parameters? You can only store arrays, Booleans, Numbers, Strings, null, and Objects in properties. Anything other than that will cause it to fail.
Can you try listening for the WidgetEvent.PARAMETERS_FAILED event and tell me if anything comes up when you enter runtime?
private function onSaveProperties(event:WidgetEvent):void {
properties.pagination = util.chk1.selected;
properties.locked = util.chk2.selected;
properties.breadcrumb = util.chk3.selected;
//this is the problem
if(util.chk1.selected == true && fileRef.name != null){
properties.fileRefference = String(fileRef.name);// This property is a string.
}
}
Hmm… I can’t see anything wrong with that. It’s confusing…
I have only just started trying WidgetFactory and just browsed through this. I was curious what the actual error was and if “fileRefference” should have 2 “f”s in it.
The API is very nice and those template methods are helpful. I like the example here as it helps us see when things are happening.
Many thanks, Tristan!
It seems that in Captivate 5 the values that you get given at Stage mode for stage.stageWidth and stage.stageHeight are much larger than the actual size of the widget. So the text file is still on stage, it’s just far off screen.
You can get around this by hard coding the position values.
Just a note, a recent try with an AS3 only FlashBuilder project and also using your example above resulted in SWFs of 0 height and width. I am debugging with MonsterDebugger so I can see the display list and see those values. Any thoughts?
Thanks!
Interesting. I got mine to work now. It was failing because I was trying to trace a property on a null object with MonsterDebugger. I didn’t get an error, the code just didn’t execute. But my issue is solved. Thanks!
Glad to hear you solved your issue, and that somehow I was helpful. Exactly how I was helpful I’m not quite sure… But don’t look a gift turtle in the mouth.
Pingback: CaptivateDev.com » Blog Archive » Choosing a Widget Framework: Widget Factory vs. CpGears
Tristan,
I’m loving the WidgetFactory 5.5. Solid work; your sense of code organization and writing style are commendable!
I am writing because I’m having some real trouble with a static widget set to “Display for Rest of Project” in a Captivate 5 project. (v5.0.2.630 to be exact).
When the widget timing is set to display for anything OTHER than “Rest of Project”, it works as expected. However, when set for “Rest of Project,” none of the template method events are being triggered. I saw a post somewhere that said you’d resolved a bug that had prevented Static Widgets from working properly with “Display for Rest of Slide.” Any chance that bug crept up again?
Hi RBean,
I think I may have fixed your problem. Can you try downloading the latest version of WidgetFactory (5.6.1) and see if that fixes the issue? http://code.google.com/p/widgetfactory/downloads/list
Thanks,
Thank you, Tristan!
I believe you did resolve the trouble. The small test widget I wrote to sniff out the events did finally list the events fired off, and it did function as expected with “Display for Rest of Project” enabled. I will go back and try it out with the actual widget project I got stalled on and update you again later. I appreciate the support!