Building custom widgets with the Zinzala SDK - page 13

Calling the method Save() on the cSettings object will save the last position of the window in the application settings file. Storing data in it, like we did in the method CloseRequested(), does not automatically save the changes to a file.

Before we look into the method Ready(), which is quiet interesting, we first need to talk a bit about how the skin shared object will be loaded and then passed down to the window. When the application is launched, the skin to be used will be passed in the command line argument. We will be using the switch -s for that. The static class sArgs provided by the SDK allows for an easy parsing of the command line. It will be used in the main of the application. Since it is static, we can use it in the Ready() method to get the path of the skin.

Now, we can start looking at Ready():

void cDApplication::Ready() { // load settings if(iSettings) iSettings->Load();

Although we have had iSettings since the constructor, we have not loaded the settings file until now. If it is the very first time the application is started, the settings file will not exist. The method Load() will fail, but it doesn't really matter since we will create the file when we save the settings in the application destructor. Now, we are going to use the method sArgs::Presents() to test if the switch was present on the command line:

if(sArgs::Presents("s")) { // load the skin cDSkin lSkin(sArgs::Value("s"));

Using the class cDSkin presented earlier, we have loaded the shared object containing the skin from the path name retrieved from the value associated with the switch -s. However, it is only after testing the validity of lSkin, will we know if the skin object was loaded correctly:

if(lSkin.IsValid()) {

If the skin was loaded properly, we can go ahead and create the window. Since the window creation can throw an exception, we will be putting it in a try...catch block:

// create & show window try { sCleanupStack::WindL();

Calling the method WindL() is mandatory in the beginning of the block. Its purpose is to prepare the cleanup stack. Note that this method can leave if something is not right. However, since we are already in the try...catch block, it's okay. The creation of the window is no surprise; we use the method NewL(). If there is no exception, the window is ready to go and we simply show it on screen:

iWindow = cDWindow::NewL(iSettings,lSkin); iWindow->Show();

The last statement inside the try block, must be a call to the method UnWind(). This will un-prepare the cleanup stack and all the objects still present on the stack will be destroyed:

sCleanupStack::UnWind(); } catch (uException &lException) {

If an exception is raised in the try block, we will be displaying the exception information and request the application to terminate:

sEnv::PrintToStream("The exception \"%s\" was raised in %s\n", sEnv::ErrorToString(lException.iWhy),lException.iWhere); Quit();

Like in the try block, we must end the catch block by a call to UnWind(). This will get all the objects on the cleanup stack to be destroyed, which is afterall the whole point of the idiom:

sCleanupStack::UnWind(); } } else { sEnv::PrintToStream("Invalid skin\n"); Quit(); } } else { sEnv::PrintToStream("No skin given\n"); Quit(); }

Last but not least, we will call the base class Ready() method required by the framework:

cApplication::Ready(); }

Here's the header and the C++ file of cDApplication.

Main

Finally, we are going to look at the contents of the main. We need to parse the command line arguments and create and start the application:

int main(tInt32 aArgc,const tChar **aArgv) { tErr lErr; cDApplication lApp; if(!(lErr = lApp.GetFault())) { // if there is args on the command line, // extract them and give them to the app if(aArgc>1) { cCan lCan(0); if(!cCan::Verify(&lCan)) { sArgs::SetCan(&lCan); sArgs::Extract(aArgc,aArgv); // Start the app if(!(lErr = lApp.Run())) // and wait for it to end lApp.WaitEnd(); else sEnv::PrintToStream("The application failed to run : %s\n", sEnv::ErrorToString(lErr)); } else sEnv::PrintToStream("The application failed to run : %s\n", sEnv::ErrorToString(kErrOutOfMemory)); } else sEnv::PrintToStream("No skin specified.\n"); } else sEnv::PrintToStream("The application construction failed : %s\n", sEnv::ErrorToString(lErr)); }

Once the application object is created, we parse the command line arguments then ask the application to run. Once this is done, we just wait for it to end using the WaitEnd() method. The class sArgs requires a cCan object in order to parse the command line. We create one on the stack.

Throughout this article, we have been using the static class sEnv a couple of times. This is an handy static class, which provides access to various useful methods, such as PrintToStream(), LeaveIfError() or ErrorToString(). The latter method transforms an error code into a human readable string.

Print version

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