Building custom widgets with the Zinzala SDK - page 16

Instead of using the method CreateBitmapFromResourceL that we implemented earlier, we are using one that keeps the created bitmap on the cleanup stack even if there is no exception. Once we have replaced all the old bitmaps by the new ones, at the end of ReSkinL(), we pop all the 17 objects we have placed on the cleanup stack. The method PopL() verifies that the last object to remove is the background bitmap. If this is not the case, something is wrong and the method will throw an exception. If everything goes according to plan, we can then redraw the whole console.

The method CreateBitmapFromResourceLC isn't much different from the one we did earlier. It simply pushes the bitmap on the cleanup stack:

cBitmap *CreateBitmapFromResourceLC(const tBitmapResource &aRes,tBool aTransparent = true) { tErr lErr; cBitmap *lBitmap = NULL; lBitmap = new cBitmap(aRes.iWidth,aRes.iHeight,eSpaceColor8Bit,true,aRes.iColors); lErr = cBitmap::VerifyD(lBitmap); if(!lErr) { sCleanupStack::PushL(lBitmap); lBitmap->SetPalette(aRes.iPalette); lBitmap->SetBits(aRes.iBits,aRes.iLength,0); if(aTransparent) lBitmap->MakeTransparent(aRes.iIndex); return lBitmap; } else throw uException(lErr,"CreateBitmapFromResourceLC()"); }

Now, let's add some extra scripting abilities to the console widget itself by supporting invocations of any of the console's buttons. By doing so, we allow remote control and automated testing capabilities, since the console can be invoked from anywhere:

#> yo hexaZen/Custom tell window.console invoke play

Because by default the widgets do not allow scripting, we are going to allow it in the window ConstructL() method:

void cDWindow::ConstructL(cDSkin &aSkin) { sEnv::LeaveIfError(iFault); iConsole = cMyConsoleView::NewL(aSkin); iConsole->AllowScripting(eLocal); AddChild(iConsole); }

Then, we will be declaring the method ScriptingMessageReceived() in the console class and implementing it. Here it is:

void cDConsoleView::ScriptingReceived(cMessage *aMessage,cMessage *aReply) { tUint32 lCmd; aReply->SetBool(kScriptItemDone,true); if(!aMessage->GetUint32(kScriptItemCommand,&lCmd)) { switch(lCmd) { case kScriptCmdInvoke: { const tChar *lArg; // if a button is already pressed, we will ignore this command if(iPressedButton == kButtonsCount) { if(!aMessage->GetString(kScriptItemArgs,&lArg)) { if(!strcmp(lArg,kScrButtonPlay) || !strcmp(lArg,kScrButtonStop)) { Pressed(kButtonPlay); Invoked(); } else if(!strcmp(lArg,kScrButtonPause)) { Pressed(kButtonPause); Invoked(); } else if(!strcmp(lArg,kScrButtonBwd)) { Pressed(kButtonBwd); Invoked(); } else if(!strcmp(lArg,kScrButtonFwd)) { Pressed(kButtonFwd); Invoked(); } else { aReply->SetBool(kScriptItemDone,false); aReply->SetUint8(kScriptItemReason,kScriptErrIncorrect); } } else { aReply->SetBool(kScriptItemDone,false); aReply->SetUint8(kScriptItemReason,kScriptErrMissingArg); } } break; } default: cView::ScriptingReceived(aMessage,aReply); } } else { aReply->SetBool(kScriptItemDone,false); aReply->SetUint8(kScriptItemReason,kScriptErrMalformed); } }

If the command in the scripting message is kScriptCmdInvoke, we retrieve its argument and compare it to the label of the console's buttons. Here's the declaration of the constants we are using to distinguish the different buttons invoked:

const tChar *kScrButtonPlay = "play"; const tChar *kScrButtonStop = "stop"; const tChar *kScrButtonBwd = "bwd"; const tChar *kScrButtonFwd = "fwd"; const tChar *kScrButtonPause = "pause";

If we were to add scriptability to all the widgets of the UI, we could then support automated testing of the applications. This will allow for a more consistent approach to testing since it is fully documented, repeatable and very flexible. Saving developers from painful manual testing also helps to keep their focus on more rewarding activities. Because it is repeatable, regression testing can be performed on a regular basis. In short, scriptability can help your product achieve a better quality in a relatively painless way. It can also ease the integration of an application in a network of collaborative applications.

6. Conclusion

By using object-oriented programming, we were able to quickly build a custom widget. Inheritance permits the use of the widget in many applications, saving time and effort. The Zinzala SDK can leverage the quality of your embedded systems, while making developers lives easier. If you are developing set-top boxes, using object-oriented techniques will help you lower the time to market of your product. A goal worth the cost of the little overhead that C++ will bring.

To obtain more information, please contact hexaZen at www.hexazen.com
Zinzala and zSDK are trademarks, registered trademarks, or service marks of hexaZen.
All other names mentioned are trademarks, registered trademarks, or service marks of their respective companies.
Copyright © hexaZen 2003-2004. All rights reserved. Zinzala/Docs/Papers/Introducing

Print version

All content © 2004-2007, hexaZen - Vancouver BC, Canada