Scenes in Tizen 2.1

Gabor Paller's picture

Android and bada had a very different view on screen transitions. Android has its activities that have a life cycle of their own and may be accessed even by other applications. In the bada application model the forms are just UI elements that may be displayed in a frame and the application is monolithic: it exposes only one entry point to the external world. While Tizen didn't change the bada application model, it did introduce an additional life-cycle element between the application and form abstraction: the scene.

 

The example project is attached to this post. You have to be logged to the Sfonge site in order to access it.

 

Scenes are form transitions, described  in a centralized way. A scene can be activated by referring to a scene ID and those scene IDs are all specified in an resource file (default: workflow.xml). The UI Builder in the Tizen tool chain makes this task visually appealing.

 

 

The UI Builder also generates skeletons of the form, form and panel factory code which is kind of nice as this boilerplate code is not trivial. Our simple application (those who participated Sfonge's bada training will find it familiar, this is the words2 example) consists of 2 forms, a list of interesting words and a detail screen for the selected word. The image above shows, how these scenes appear in the UI Builder. Each form is encapsulated in a scene container (e.g. ID_SCN1). The scene transitions are modeled as arrows among the scenes. Except for the App Start state which is special, the starting point of a scene transition arrow must be an event handler in the starting form (an event handler can be added with the "Add event handler ..." option in the UI Builder's floating menu). The other end of the scene transition arrow is another scene.

 

From this information the UI Builder generates code like this:

 

void
Listform::OnItemStateChanged(const Tizen::Ui::Control& source, int index, int itemId, Tizen::Ui::ItemStatus status)
{
...
    SceneManager* pSceneManager = SceneManager::GetInstance();
    pSceneManager->GoForward(SceneTransitionId(ID_SCNT_2));
}

The ... stands for code that I have added by hand. The rest was generated by the UI Builder. ID_SCNT_2 is the scene transition ID that the UI Builder allocated to the scene transition between the scenes IDSCN_1 (containing ListForm) and IDSCN_2 (the one with WordForm). In comparison, let's see how the above piece of code would have looked like in the old-style form-based code (available both in bada 2.0 and Tizen 2.1).

 

void ListForm::OnItemStateChanged( const Control &source, int  index, int  itemId, ItemStatus  status ) {
        Frame *frame = Application::GetInstance()->GetAppFrame()->GetFrame();
...
        WordsForm *wordsForm = new WordsForm( db, this, index );
        wordsForm->Initialize();
        frame->AddControl( *wordsForm );
        wordsForm->Draw();
        wordsForm->Show();
}

 

The old-style code has to take care of creating the form object, adding the form to the scene and get it drawn. In the scene-style code everything was delegated to the scene manager. The scene manager takes care of instantiating and displaying the appropriate form object and it can even cache that instance if the scene transition arrow defines the destroy policy as "keep". The scene transition allows all sorts of goodies to be set, e.g. one can define scene change animation like the one between the ListForm (going out to the left) and the WordsForm (coming in from the right) below.

How does the SceneManager know, how to instantiate form instances? A helper class instance (words2withsceneFormFactory in the case of the example project) is registered with the scene manager which has the factory method for forms (CreateFormN). A similar helper class exists for panel-based scenes (words2withscenePanelFactory) but this example program does not use panel-based scenes. These classes are created and managed by the UI Builder so we don't have to care too much about them, except for one thing. Here is how the WordsForm instance is created in words2withsceneFormFactory::CreateFormN method.

 

if (formId == IDF_WORDSFORM)
    {
        Wordsform* pForm = new Wordsform();
        pForm->Initialize();
        pNewForm = pForm;
    }
...

 

Now in the old-style form-based code, the constructor was used to set up parameters of the instance, e.g. the index of the word in the word database. As the scene transition method (SceneManager::GoForward) cannot pass parameters to the incoming scene and it is not guaranteed that the form is instantiated when the scene transition happens (because of the "keep" policy, form instances may be cached) plus the form is initially instantiated by the boilerplate factory code, parameter passing to the incoming form is not that easy. I created accessor methods in the main Application instance because that instance is easily accessible anywhere in the application like this:

 

words2withsceneApp* pApp = 
static_cast<words2withsceneApp*>( Tizen::App::App::GetInstance() );


The main Frame instance could be accessed also quite easily. 
But passing the word index through the Application instance 
just because ListForm and WordsForm can both access the Application instance easily 
but they can't communicate that easily with each other simply does not feel right
 and later on with more complex applications it will definitely result in hard to maintain spaghetti code. 
In Android there is the Activity invocation Bundle for these kinds of tasks.

SceneManager not only can do forward transitions, it builds a scene history stack and the application can easily step backward in the stack.

SceneManager* pSceneManager = SceneManager::GetInstance();
pSceneManager->GoBackward(BackwardSceneTransition(SCENE_TRANSITION_ANIMATION_TYPE_RIGHT));

 

There is no "back" button on Tizen devices, however, so this feature can be exploited only programmatically. In this example I had to define a button so that I can bind this piece of code to some event.

Attached file: 
Taxonomy upgrade extras: