UIQ Technology
Symbian OS Library

UIQ 3.1 SDK        UIQ developer portal

[Index] [Spacer] [Previous] [Next]



UIQ Views - How to Work with View Classes


Contents

1 Introduction

1.1 View base class

1.2 Multi-page view base class

1.3 Further reference

2 Architecture

3 Basic use of the view base classes

3.1 Includes

3.2 Construction and life cycle of a view

3.3 Focus handling

3.4 DNL - Navigation - View switch

3.5 Application Title Bar

3.6 View Context Bar

3.7 Button Bar

3.8 Zoom handling

3.9 View Mode - Full Screen Mode

3.10 UI configurations

3.11 How to handle pages and tabs

3.12 Category handling

4 Advanced use of the view base classes

4.1 Construction and life cycle of a view

5 Answers to some FAQ about migrating from UIQ 2 to UIQ 3

6 Glossary

[Top]


1 Introduction

The purpose of this guide is to explain the most common use cases of the classes CQikViewBase and CQikMultiPageViewBase. The purpose of this document is also to give concrete examples of how to implement these use cases.

The views of an application are owned by the AppUi object, the CQikAppUi based application class.

The document is divided into two main parts, one basic part and one advanced part. The basic part describes a very simple use case using the CQikViewBase class. All that is needed to bring up a single page view is described in the QHelloWorld example which is included in the SDK. The advanced part describes additional and optional parts of the view classes; this part is needed when implementing more advanced views. Examples of contents in this part are: How to use the CQikMultiPageViewBase class, how to use the view context bar and how to use categories. The more advanced examples included in the SDK are used in this part.


1.1 View base class

The class CQikViewBase is a base class for views. All UIQ views should derive from this class or the CQikMultiPageViewBase class. The CQikMultiPageViewBase class inherits from the CQikViewBase class, too. The CQikViewBase class handles much the new functionality found in UIQ 3:

Here are some screen shots from an example application that uses a view with a single page without tabs:

Softkey style Pen style

The view class inherits from the CQikVie...

The view class inherits from the CQikViewBase class.

The view class inherits from the CQikVie...

The view class inherits from the CQikViewBase class.


1.2 Multi-page view base class

The class CQikMultiPageViewBase is a base class for views with multiple pages.

Here are some screen shots from an example application that uses a view with multiple pages and tabs:

Softkey style Pen style

The view classes inherit from the CQikMu...

The view classes inherit from the CQikMultiPageViewBase class.

The view classes inherit from the CQikMu...

The view classes inherit from the CQikMultiPageViewBase class.


1.3 Further reference

See other UIQ Developer Library Documents:

See UIQ API Reference for:

[Top]


2. Architecture

High-level architecture of view classes

High-level architecture of view classes

[Top]


3. Basic use of the view base classes


3.1 Includes

Use one of the following #include directives in your view class:

#include <QikViewBase.h>

or

#include <QikMultiPageViewBase.h>

Use the following LIBRARY directive in the project's mmp-file:

LIBRARY qikcore.lib


3.2 Construction and life cycle of a view

To create a view that supports the new framework, you need to inherit from the CQikViewBase class. Your class declaration looks like this:

class CMyView : public CQikViewBase

The construction of the view object is divided into a couple of stages, to provide efficient and fast startup of the application. In this way, the view is not fully constructed before it is really needed. The constructor of the view can in a simple case look like this:

CMyView::CMyView(CQikAppUi& aAppUi) : CQikViewBase(aAppUi, KNullViewId)
    {
    }

The second parameter passed to the view base class is an ID of the parent view. This is the logical view that is normally activated when a back command is issued. For the application's default view, however, it is common to pass KNullViewId as the second parameter; this causes the user to exit the application when issuing the back command.

The ConstructL() method of the view class can look like this:

void CMyView::ConstructL()
    {
    BaseConstructL();
    }

When implementing the method ConstructL(), the first thing to do must be to call the method BaseConstructL(), which takes care of basic initiation of member data of the class.

The contents, containers and UI controls of the view are often not created in the method ConstructL(); it is more common and efficient to do this in the method ViewConstructL(). If it is necessary to create a control and add it to the view as early as in ConstructL(), then from within this method call PreemptViewConstructionL(); this causes the view framework to call ViewConstructL(). This should normally be avoided due to the increase of the application's start-up time. The method ConstructL() now looks like this:

void CMyView::ConstructL()
    {
    BaseConstructL();
    }

The factory method NewLC() of the view class is called from the AppUi class:

CMyView* CMyView::NewLC(CQikAppUi& aAppUi)
    {
    CMyView* self = new(ELeave) CMyView(aAppUi);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

The pure virtual method ViewId() that must be implemented by the view class can look like this:

TVwsViewId CMyView::ViewId()const
    {
    return TVwsViewId(KUidMyApp, KUidMyView1);
    }

This method, which is called by the application framework, returns a unique identifier of the view. This ID consists of two parts: the application UID and the view UID. More information about UID is available in Symbian OS Developer Library, see Further Reference. The view UID only needs to be unique within the application. It is recommended to use a view UID between 0x00000001 and 0x0fffffff; UIDs outside this range are reserved.

The method ConstructL() of the AppUi class inherits from the CQikAppUi class. It is common that this method creates the view by calling the method NewLC() of the view class. The view object is also added to the AppUi object in this method by calling AddViewL():

void CMyAppUi::ConstructL()
    {
    CQikAppUi::BaseConstructL();

    CMyView* myView = CMyView::NewLC(*this);
    AddViewL(*myView);
    CleanupStack::Pop(myView);
    }

AddViewL() registers the view and puts it on the control stack. Ownership of the view is transferred to CQikAppUi so you do not need to unregister and delete it yourself; this will be done by the destructor of CQikAppUi.

ViewConstructL

This method fully constructs the view; it is called by the application framework when the view is activated for the first time. All of the elements in the view should be available after a call to this method. The following example shows how to use the View Framework to construct the view by using data from a resource file.

/**
Called the first time a view is activated
*/
void CMyView::ViewConstructL()
        {
        ViewConstructFromResourceL(R_UI_CONFIGURATIONS);
        }

It is not a requirement, but it is recommended to add the controls constructed in C++ code to the view by appending them to the CCoeControlArray. Since CQikViewBase inherits from CQikContainer, the access method to get the CCoeControlArray is called Controls(). This is how it is done:

_LIT(KText,"MyLabel");
CEikLabel* labelCtrl = new (ELeave) CEikLabel;
Controls().AppendLC(labelCtrl); //Do not push on Cleanup Stack before
labelCtrl->ConstructL();
labelCtrl->SetTextL(KText);
CleanupStack::Pop(labelCtrl);

ViewActivatedL

This method can be used to initialize the view and is called every time the view is activated. This method can be used to update the view with current user data which can include adding new view content and commands:

/**
Called every time a view is activated
*/
void CMyView::ViewActivatedL(   
        const TVwsViewId& /*aPrevViewId*/,
        TUid /*aCustomMessageId*/,
        const TDesC8& /*aCustomMessage*/)
        {
        // Update the controls included in the view with new data.
        }

ViewDeactivated

This method is called every time a view is deactivated. It can be used to remove view content and commands on view deactivation:

/**
Called every time a view is deactivated
*/
void CMyView::ViewDeactivated()
    {
    // Removes focus from the focused control.
    RequestFocusL(NULL);
    }

Creating and adding controls dynamically

This section describes how to create view content and command lists on view activation and destroy them on view deactivation. This is done so that UI objects do not need to be held in memory all of the time. Although this can be useful under some circumstances, we do not recommend this when developing applications. This is because:

/**
Set the command_list member of your QIK_VIEW_CONFIGURATION structs to zero to prevent command lists from being auto-loaded by ViewConstructFromResourceL()
*/
RESOURCE QIK_VIEW_CONFIGURATIONS r_ui_configurations
    {
    configurations =
        {
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            command_list = 0;
            view = r_layout;
            }
        };
    }

/**
Overrides InitializeViewFromResourceL to prevent it from being executed twice at program start up when you also call it from your ViewActivatedL. (It is also called from inside ViewConstructFromResourceL)
*/
void CMyView::InitializeViewFromResourceL(const TQikViewConfigData& aViewConfigData)
        {
        if( iAppUi.IsViewConstructed(ViewId()) )
            CQikViewBase::InitializeViewFromResourceL(aResourceId);
        }

Summary

In summary, follow these steps to quickly create a view:

  1. Set the logical back view in CQikViewBase's constructor, the parent view parameter,

  2. Implement the pure virtual method CQikViewBase::ViewId(),

  3. Call the method CQikViewBase::BaseContructL() as the first step in the view class method ConstructL(),

  4. Add the view object to the CQikAppUi object by calling the method CQikAppUi::AddViewL(),

  5. Load UI configurations, controls, layouts and commands in your view's ViewConstructL() method,

  6. Use CCoeControlArray for compound controls and views.


3.3 Focus handling

For hardware-key navigation to work correctly, you need to make sure you set a control's parent. The parent is the compound control that owns the control. This is done automatically when you call SetContainerWindowL(CCoeControl) for a control. Otherwise, use the CCoeControlArray to add component controls or let the view framework construct your controls from resource data. This is also done automatically when adding the control to an existing container control like the view class. A control's parent can also be set with CCoeControl::SetParent().

You should use layout managers for navigation to function as expected. If you do not use layout managers, navigation could be inconsistent. Without layout managers, navigation is performed by calculating the distance to controls in the desired direction. The distance is currently calculated by comparing the controls' center positions.

Also, make sure that the controls that are not supposed to have focus are set up as non-focusing and those that are supposed to have focus are set up as focusing. Use CCoeControl::SetFocusing() to set this. The default setting in CCoeControl is non-focusing. However, many stock controls, which are able to receive focus, override this. If a child control wants to have focus, but its compound parent does not want to have focus, only the child control needs to be a focusing control.

To manually give focus to a control, use the CQikViewBase::RequestFocusL() method. This will take care of calling PrepareFocusLossL() and PrepareFocusGainL() throughout the whole focus chain and it will also set/reset focus on the appropriate controls in focus chains.

If you use CQikViewBase::RequestFocusL() you should not call PrepareFocusLossL() and PrepareFocusGainL() for the controls in the control chain. If you want to set focus manually with CCoeControl::SetFocus(), you need to make sure that PrepareFocusLossL() and PrepareFocusGainL() are called for all the controls in the focus chain that change focus. For most cases, RequestFocusL() is sufficient, so avoid using SetFocus() in UIQ 3.

If you want automatic focus transitions when selecting controls, you need to set your view as the control observer of the control with CCoeControl::SetObserver(). CQikViewBase::HandleControlEventL() will then take care of requesting focus for the control. If you define your view in a resource file, the view is automatically set as your control's observer.

If a view has tabs, the left and right navigation keys are used to switch tabs if the key event is not consumed by any control or focus transition.

OfferKeyEventL

The base view’s OfferKeyEventL() will forward hardware-key events downward in the focus chain. This means that parent controls get a chance to consume key events before they reach the child controls. Make sure to call the view base’s OfferKeyEventL() if you override this method.

Initial focus

One entry should be highlighted when a view is launched. The method SetInitialFocusL() is used to set the focus unless there is already a control with focus. The default implementation sets focus on the first focusing control, which should be correct for most views. However, you can override SetInitialFocusL() to set the focus on any control. If you want focus to be reset, for example when you back away from a view, you can call RequestFocusL(NULL) or SetInitialFocusL().


3.4 DNL - Navigation - View switch

Back links

Going back takes the user to the previous view. This could be the view in another application that used a DNL to the current view or the view's parent view. All views, except the base/default view, normally have a parent view. The first view added to the AppUi becomes the default view, but this can be overridden by calling CCoeAppUi::SetDefaultViewL(). When going back from the application’s default view, the user ends up in the system default view.

Back links example

Back links example

Here is an example of how to handle back behavior:

void CMyView::HandleCommandL(CQikCommand& aCommand)
    {
    switch(aCommand.Id())
        {
        case EMyCmdOk: // SaveL will be called asynchronously
            RequestFocusL(NULL); //see 2.5.3.3
            ActivatePreviousViewL(ESave);
            break;
        case EQikCmdGoBack: // Cancel – SaveL will NOT be called
            RequestFocusL(NULL); //see 2.5.3.3
            ActivatePreviousViewL(ECancel);
            break;
        default:
            CQikViewBase::HandleCommandL(aCommand);
            break;
        }
    }

Note: Back links are only remembered between views, not in dialogs.

Saving data

CQikViewBase implements a virtual SaveL() method which is overridden by views that want to save data to a disk. SaveL() is called:

  1. At view deactivation, caused by a call to CQikViewBase::ActivatePreviousViewL(),

  2. At view deactivation, caused by a call to CCoeAppUi::ActivateViewL(TVwsViewId&),

  3. At activation of the same view that is already active. This is typically due to a notifier using CCoeAppUi::ActivateViewL(TVwsViewId&),

  4. When SaveThenDnlToL(TVwsViewId&) is called.

SaveL() is not called when executing CQikViewBase::ActivatePreviousViewL(ECancel). ActivatePreviousViewL(ECancel) can be called directly, but it is also executed when CQikViewBase::HandleCommandL(CQikCommand&) handles the EQikCmdGoBack command.

It is up to each application to display the CQikSaveChangesDialog to warn users about unsaved data.

Single task navigation

When a user returns to an application that was switched away from by using the back key, the view tab and highlight position are shown in their default positions.

Resetting the highlight, the scrollable container and the selected tab on back navigation events is the responsibility of each application. This behavior can be achieved, for example, by intercepting EQikCmdGoBack events in HandleCommandL(CQikCommand&) and there removing focus by calling RequestFocusL(NULL) before passing the event to the base implementation of HandleCommandL().

Using multiple applications to complete a task

Using multiple applications to complete a task requires that the state remains unchanged in applications left by switching away, instead of being left by using the back option. The next time the application is activated, the application state, that is, the selected view, the selected tab and the scroll position, are just as they were when the application was deactivated except that menus and active pop-outs are closed. For this navigation approach to work, your application cannot delete view content when the view is deactivated.

If an application is left in a specific state as described above, the state will be lost if another application uses a DNL to switch to the application.

Summary

To support back behavior:


3.5 Application Title Bar

The Application Title Bar, as default, shows the application name. When CQikViewBase::SetCategoryModelAsCommandsL() has been called, the Application Title Bar displays the name of the selected category instead of the application name when any other category than "All" is selected.

Application title bar in Pen style

Application title bar in Pen style

Application title bar in Softkey style

Application title bar in Softkey style

The Application Title Bar also functions as a command operator when the UI configuration is EQikUiConfigMenu, rather than EQikUiConfigSoftkey. The command types the different drop-down menus accept, as well as some of the other parameters, are configurable by phone manufacturers in QikCtl.rss.

When the Category title contains just one item, pressing the title has the same effect as opening the menu pane, selecting the item and closing the menu pane, but no menu pane will be opened graphically. If the item supplies an icon, that icon will replace the icon for the Category title. A phone manufacturer can turn on/off this behavior system wide from the resource file.

The Application Title Bar resides above the application area. It is not directly reachable for an application developer. The idea is that the Command Processing Framework, together with the current UI configuration, decides which commands are added to the Application Title Bar and thereby are displayed to the user. Any other interaction with the Application Title Bar is performed through the Category Model or the View Base Class. A developer should not, under any circumstances, try to access the Application Title Bar directly.

On a phone using softkey style, the Application Title Bar does not accept input from the user; it simply acts as an information bearer. On a phone with a touchscreen, the Application Title Bar replaces the former menu bar. In the standard configuration, the Application Title Bar has two titles, one text title that opens up the application's menu and one icon title that typically opens up the Category menu.

The text on the title is usually the name of the application. If the Category Model is used, the chosen Category's name will be shown instead of the name of the application after a category has been selected. Selecting the "All" category, determined by handle, not by name, will once again show the name of the application.

If you want to change the currently selected category from code, call CQikViewBase::SelectCategoryL(TInt aHandle). This method is protected and will update the current category and change the title in the Application Title Bar. This is useful when entering a detail view with an item from a given category. The category name should never be set by calling SetAppTitleNameL().

If the name of the application needs to be changed, call SetAppTitleNameL(). If the icon needs to be changed, call SetAppTitleIcon(). Calling them with KNullDesC() and NULL respectively results in resetting them to the original name/icon.


3.6 View Context Bar

TODO! The view context bar can contain different types of controls. Texts and icons are examples of controls that can be added and handled through the interface MQikViewContext provided by the CQikViewBase. Tabs are handled directly through the interface MQikTab provided by the CQikViewBase.

The View Context Bar is owned by the view, and not shared between views as is the Application Title Bar. It resides inside the Application Title Bar, to the right of the application icon and below the title. The View Context Bar has no public APIs. Interaction is handled by retrieving an MQikViewContext from the view.

View context bar displaying tabs

View context bar displaying tabs

The View Context Bar has two purposes: to display and handle tabs and to add decorations.

The tabs are handled through CQikViewBase or CQikMultiPageViewBase. CQikMultiPageViewBase implements the system with tab pages. As long as your applications use tab pages, you just need your view to inherit from CQikMultiPageViewBase. If you do not use tab pages or want to use the tabs in a customized way, inherit from CQikViewBase. Special implementations can inherit directly from CQikViewBase and make use of the tabs in customized ways.

To add texts and icons to the View Context Bar, call ViewContext() in the view. This gives you an interface, MQikViewContext, to the View Context Bar. With this interface you can add texts, add icons, change the text, remove texts, etc.

It is worth noting that the component IDs you use when adding/deleting range from 1 to 999 and then from 1001 and upwards. The first series makes them left aligned, while the second will make them right aligned. The use of 0 and 1000 is strongly discouraged. Do not expect your code to work if you try to use them. A component with a higher numbered ID is granted placement to the right of a component with a lower numbered ID.


3.7 Button bar

In Pen style, applications have a button bar that contains, as a minimum, a back button. The back command is automatically added to all applications and does not need be included as part of the application specific commands.

Examples of Button bar content

Examples of Button bar content

How to control command distribution

Commands of type EQikCommandTypeYes, EQikCommandTypeDone, EQikCommandTypeNo and EQikCommandTypeCancel are automatically consumed by the button bar as long as there is enough room.

If a command is used in the button bar, it is also consumed, that is, it is not passed on to other command operators.

The following commands will automatically be added as buttons to the button bar if they fit:

The button bar may also contain a default button, which differs in appearance from the other buttons, and is mapped to the hardware confirm key. To specify a button as the default button, use the flag EQikCpfFlagIsDefault.

But it is to be noted that if the view or the control that has focus contains an EQikCommandTypeItem command which is not flagged with EQikCpfFlagPreferToBePlacedInButtonbar, the command will be consumed by the CQikKeyListener and mapped to the hardware confirm key. The result is that the default button is not invoked on the hardware confirm key.

Number of buttons

If all of the buttons have an image, it is only available space that limits the number of buttons in the button bar. An icon button has a minimum size of 1/9 of the button bar width, minus margins.

Buttons with text grow as the text grows, but as a minimum they are 1/3 of the button bar width, minus margins.

If too many commands are received by the button bar, that is, more than three text buttons or more buttons than fit within the available space, some buttons will be discarded and the corresponding commands passed on to other command operators. The commands will be discarded in the following order:

Button order

The buttons will be arranged according to type in the following order from left to right:

The buttons are left aligned within the button bar.


3.8 Zoom handling

CCoeControl support of Zoom state

To improve support for zooming, and to allow controls to have text in different font sizes, depending on, for example, the current screen mode, improved support for zooming has been added to Cone. It is now possible to attach a TZoomFactor to every CCoeControl using this new CCoeControl method:

class CCoeControl
public:
    IMPORT_C void SetZoomFactorL(TInt aZoomFactor, TZoomType aZoomType = ERelativeZoom);

The zoom factor assigned to a control applies to that control and to all the children inside. The zoom factor can be absolute, or relative to that of the control's parents. To retrieve a control’s accumulated zoom factor, call the new CCoeControl method:

class CCoeControl
protected:
    IMPORT_C TZoomFactor AccumulatedZoom() const;

When the zoom factor of a control is changed, a KEikMessageZoomChange message is sent to the HandleResourceChange() method of all of the affected controls, and there is a subsequent call to the new CCoeControl::RequestRelayout() method of the control whose zoom has changed.

The zoom factor used for an entire application can also be changed by setting the CCoeEnv's zoom factor, which has been moved to CCoeEnv from CEikonEnv.

For more information about how this new API is used to control the size of a control's fonts, see below.

Handle SetZoomFactorL() in ViewConstructL()

Here is an example from the SDK example QMyDirectory. This code sample shows how to set the zoom factor to the most recently saved value for the specific view:

/**
Inherited from CQikViewBase and called upon by the UI Framework. It creates the view from resource, sets the zoom level and initiates all controls to default values.
*/
void CMyDirectoryDetailView::ViewConstructL()
    {
    // Loads information about the UI configurations this view supports
    // together with definition of each view, its layout and commands.
    ViewConstructFromResourceL(R_MYDIRECTORY_DETAILVIEW_UI_CONFIGURATIONS, R_MYDIRECTORY_DETAILVIEW_CONTROLS);

    //Get zoom state from the document and set zoom factor
    CMyDirectoryDocument* document = static_cast<CMyDirectoryDocument*>(iQikAppUi.Document());
    SetZoomFactorL(document->Preferences().DetailViewZoomState());

How to implement a "change zoom factor" user command

Here is an example from the SDK example QMyDirectory. This code sample shows how a "change of zoom factor" command can be handled and implemented by the view class:

/**
Handles all commands in the view. Called by the UI framework when a command has been issued. The command IDs are defined in the .hrh file.
*/
void CMyDirectoryDetailView::HandleCommandL(CQikCommand& aCommand)
    {
    switch(aCommand.Id())
        {
        ...
        case EMyDirectoryZoomCmd:
            {
            // Launch the zoom dialog
            CMyDirectoryDocument* document = static_cast<CMyDirectoryDocument*>(iQikAppUi.Document());
            const TInt zoomFactor = CQikZoomDialog::RunDlgLD(document->Preferences().DetailViewZoomState());
            
            // If zoom state have changed it will be stored to persistent
            // storage and a relay out will be performed
            if(document->Preferences().SetDetailViewZoomState(zoomFactor))
                {
                // Sets the zoom factor for the view
                SetZoomFactorL(zoomFactor);

                // Make a relay out of the view for the new zoom level
                PerformLayout();
                }
            break;
        ...


3.9 View mode - Full Screen mode

The base view class implements support for full screen in Softkey style.

The view mode is represented by a class called TQikViewMode. To retrieve the current view mode, use CQikViewBase::ViewMode(). This fills TQikViewMode with Boolean values concerning the use of the various pieces of screen furniture that comprise the current view mode. Then, use the exported functions in TQikViewMode to inquire whether a specific piece of screen furniture is being used or not. For example, UsesAppTitleBar() returns ETrue if the Application Title Bar is being used in the current view mode and EFalse if it is not being used.

Updating the view mode is also a two stage process. First, use the exported functions in TQikViewMode to set the Boolean values in the TQikViewMode object. These determine which pieces of screen furniture will be used in the view mode once it is updated. For example, calling SetButtonOrSoftkeyBar(ETrue) adds the button bar or softkey bar to the list of screen furniture in the TQikViewMode object; calling SetButtonOrSoftkeyBar(EFalse) removes the button bar or softkey bar from the list. Once all of the values in the TQikViewMode object have been updated to reflect the new view mode, pass the list, the TQikViewMode object, as an argument to CQikViewBase::SetViewModeL() to finally set the view mode.

NONSHARABLE_CLASS(TQikViewMode)
    {
public:
    IMPORT_C TQikViewMode();
    IMPORT_C void SetAppTitleBar(TBool aUsed);
    IMPORT_C TBool UsesAppTitleBar() const;
    IMPORT_C void SetButtonOrSoftkeyBar(TBool aUsed);
    IMPORT_C TBool UsesButtonOrSoftkeyBar() const;
    IMPORT_C void SetStatusBar(TBool aUsed);
    IMPORT_C TBool UsesStatusBar() const;
    IMPORT_C void SetToolbar(TBool aUsed);
    IMPORT_C TBool UsesToolbar() const;
    IMPORT_C void SetNormal();
    IMPORT_C TBool IsNormal() const;
    IMPORT_C void SetFullscreen();
    IMPORT_C TBool IsFullscreen() const;
    IMPORT_C TBool operator==(const TQikViewMode& aOther) const;
    IMPORT_C TBool operator!=(const TQikViewMode& aOther) const;
    …
    }

class CQikViewBase
        {   
public: // View mode
        IMPORT_C TQikViewMode ViewMode() const;
        …
protected:
        IMPORT_C void SetViewModeL(const TQikViewMode& aMode);
        …
        }

Activate Full Screen mode

The code samples below show how different pieces of screen furniture can be set available or not available in a specific view mode. The Full Screen view mode is activated by calling SetFullscreen(). This is a composite state meaning that no screen furniture is available; Application Title Bar, Button Bar, Softkey Bar and Status Bar are all not available.

Be aware that when using Full Screen mode, only the command operator taking care of hardware-key events is available. So usually you need another command operator. See the next section which describes the Full Screen Floating Menu which is a command operator that can take care of the remaining commands.

    // Controls if the Application Title Bar is to be available in this view mode.
    TQikViewMode viewMode = ViewMode();
    viewMode.SetAppTitleBar(EFalse);
    SetViewModeL(viewMode);
    
    // Controls if the Button or Softkey Bar is to be available in this view mode.
    TQikViewMode viewMode = ViewMode();
    viewMode.SetButtonOrSoftkeyBar(EFalse);
    SetViewModeL(viewMode);
    
    // Controls if the Status Bar is to be available in this view mode.
    TQikViewMode viewMode = ViewMode();
    viewMode.SetStatusBar(EFalse);
    SetViewModeL(viewMode);
    
    // Controls the Full Screen view mode. This method activates this specific mode.
    // Full Screen mode is the opposite state to the normal mode.
    TQikViewMode viewMode = ViewMode();
    viewMode.SetFullscreen();
    SetViewModeL(viewMode);
    
    // Controls the Normal view mode. This method activates this specific mode,
    // normal mode is the opposite state to the Full Screen mode.
    TQikViewMode viewMode = ViewMode();
    viewMode.SetNormal();
    SetViewModeL(viewMode);

Remaining commands

The Full Screen Floating Menu, CQikFullscreenFloatingMenu, can take care of the remaining commands which cannot be assigned to some of the standard command operators. This is very useful for applications using Full Screen mode where the standard command operators such as Application Title Bar and Softkey Bar are unavailable.

The following example shows how this control can be used:

#include <QikFullscreenFloatingMenu.h>
...

CMyView::~CMyView()
    {
    ...

    if(iFloatingMenu)
        {
        // The custom command operator must be removed from the command manager. 
        CQikCommandManager::Static(*iCoeEnv).RemoveCustomOperator(*this,*iFloatingMenu);

        iFloatingMenu = NULL; // No need to delete the member, it is in the CCoeControlArray.
        }
    }

void CMyView::ViewConstructL()
    {
    ...

    iFloatingMenu = CQikFullscreenFloatingMenu::NewL(*this);

    // Append the control to the CCoeCOntrolArray
    AddControlLC(iFloatingMenu);        // iFloatingMenu is pushed on the CleanupStack

    // The custom command operator must be added to the command manager.    
    CQikCommandManager::Static(*iCoeEnv).AddCustomOperatorL(*this,*iFloatingMenu);

    CleanupStack::Pop(iFloatingMenu);

    // iFloatingMenu, like all other children, will be activated by the system with ActivateL().

    ...
    }


3.10 UI-configurations

A view uses the QIK_VIEW_CONFIGURATIONS resource structure to define which UI configurations it supports.

If an application view, for example, supports portrait mode only and the phone tries to launch such a view when currently in landscape mode, the phone will switch to portrait mode. An application can only be started in a UI configuration it supports. However, as an aid during development, the emulator can force an application into an unsupported screen mode with the window server's debug keys.

Please refer to other documents for more information regarding UI configurations in UIQ Developer Library.

The example below sets up a view to support two different UIQ configurations.

Softkey style Pen style

Interaction Style:

Softkeys

Menu bar

Touchscreen:

No

Yes

Screen mode:

240*320 pixels (portrait mode)

240*320 pixels (portrait mode)

RESOURCE QIK_VIEW_CONFIGURATIONS r_refui_configurations
    {
    configurations =
        {
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            },
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikPenStyleTouchPortrait;
            }
        };
    }

The QIK_VIEW_CONFIGURATIONS resource structure is loaded by calling CQikViewBase::ViewConstructFromResourceL() from ViewConstructL().

Apart from defining the supported UI configurations, you can also use QIK_VIEW_CONFIGURATIONS to set up the view to switch layout and command list automatically when changes of UI configuration occur. This is done with the view and command-list members of the QIK_VIEW_CONFIGURATIONS.

Look into other UIQ How-To guides to see code examples using resource driven layout.


3.11 How to handle pages and tabs

Adding and removing pages

Below is an example showing how to construct a page for a view and add it to a view class which inherits from the CQikMultiPageViewBase class. The example code shows the construction of the page and how to add a scrollable container to the page. A layout manager is also created and set for both the page and the scrollable container. Specific layout data is also created and set for the layout manger of the page. The example also shows how to temporarily remove the page by calling ReleasePageL() and then how to bring it back again. Finally, the example shows how to delete the page by calling DeletePage().

Constructing the page:

void CMyView::ViewConstructL()
    {
    ...
    
    _LIT(KMyTabText, "Control");
    CQikContainerBase* controlPage = ConstructPageL(EMyAddPage, KMyTabText, NULL, NULL);
        
    CQikRowLayoutManager* rowLayout = CQikRowLayoutManager::NewLC();
    controlPage->SetLayoutManagerL(rowLayout);
    CleanupStack::Pop(rowLayout);
    
    CQikScrollableContainer* container = new (ELeave) CQikScrollableContainer();
    controlPage->AddControlLC(container);
    container->ConstructL(ETrue);
    container->SetUniqueHandle(EMyAddPageScrollableContainerCtrl);
    container->ScrollBarFrame()->SetScrollBarManagement(CEikScrollBar::EVertical, CEikScrollBarFrame::EComponent);
    container->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
    
    CQikRowLayoutManager* rowLayout2 = CQikRowLayoutManager::NewLC();
    container->SetLayoutManagerL(rowLayout2);
    CleanupStack::Pop(rowLayout2);
    CleanupStack::Pop(container);
    
    CQikRowLayoutManager::TLayoutData layoutData;
    layoutData.iHorizontalAlignment = CQikLayoutManager::EHAlignFill;
    layoutData.iVerticalAlignment = CQikLayoutManager::EVAlignFill;
    layoutData.iVerticalExcessGrabWeight = 1;
    static_cast<CQikRowLayoutManager*>(controlPage->LayoutManager())->SetLayoutDataL(*container, layoutData);
    
    _LIT(KMyAddText, "My add text");
    CEikEdwin* ctrl = new (ELeave) CEikEdwin();
    container->AddControlLC(ctrl, EMyAddPageEdwin);  //Do not push on Cleanup Stack before
    ctrl->ConstructL();
    ctrl->SetUniqueHandle(EMyAddPageEdwin);
    ctrl->SetTextL(&KMyAddText);
    ctrl->SetObserver(this);
    CleanupStack::Pop(ctrl);                    
    
    PerformLayout();
    ...
    }

Deleting the page:

DeletePageL(EMyAddPage);

Handling tabs

Here are some examples of how to handle tabs.

Add a tab:

_LIT(KMyTabText, "Tab");
AddTabL(EMyAddTab, KMyTabText);

Remove the tab:

RemoveTabL(EMyAddTab);

Dim or make the tab invisible:

MQikTab* tab = Tab(EMyAddTab);

if(tab)
{
if(tab->IsVisible())
    {
    tab->SetVisible(EFalse);
    }
else
    {
    tab->SetVisible(ETrue);
    }
}

if(tab)
{
if(tab->IsDimmed())
    {
    tab->SetDimmed(EFalse);
    }
else
    {
    tab->SetDimmed(ETrue);
    }
}


3.12 Category handling

Categories are used to divide user data into user-definable sets and act as a filter in the application list view. Categories have already been used extensively in UIQ 2. The framework for category support has been left untouched in UIQ 3. However, CQikViewBase has been equipped with some glue to merge category support and the command processing framework.

CQikViewBase::SetCategoryModel(CQikCategoryModel*) is used to associate a category model with a view. The view takes ownership. Ownership can be retracted by calling SetCategoryModel(CQikCategoryModel*) with NULL as the parameter.

CQikViewBase::SetCategoryModelAsCommandsL() will create a command corresponding to each of the categories in the view’s category model. It also makes the view base the observer of the category model; changes in the category model are automatically transferred to the CPF.

Category commands are displayed in a special menu pane in the Application Title Bar.

In Softkey style, categories are cascaded from the More menu. To change the label, grouping or sorting of the More menu's cascaded categories command, use the view’s DynInitOrDeleteCommandL callback:

CQikCommand* CMyView::DynInitOrDeleteCommandL(CQikCommand* aCommand, const CCoeControl& /*aControlAddingCommands*/)
    {
    switch(aCommand->Id())
        {
        case EQikSoftkeyCmdSelectCategory:
            {
            // commands are sorted by type+group+prio
            aCommand->SetGroupId(EMyCategoryGroupId);    
            aCommand->SetPriority(-1);
            break;
            }
        default:
            break;
        }
    return aCommand;
    }


4 Advanced use of the view base classes

4.1 Construction and life cycle of a view

If the view class inherits from CQikMultiPageViewBase, the Page() method can be used to get the container of the page to add the controls to.

_LIT(KText,"MyLabel");
CQikContainerBase* container = Page(EMyPage);
if(container != NULL)
    {
    CEikLabel* labelCtrl = new (ELeave) CEikLabel();
    container->Controls().AppendLC(labelCtrl); //Do not push on Cleanup Stack before
    labelCtrl->ConstructL();
    labelCtrl->SetUniqueHandle(EMyLabel);
    labelCtrl->SetObserver(this);
    labelCtrl->SetTextL(KText);
    CleanupStack::Pop(labelCtrl);   
    }

This is what you do to add the control to an existing scrollable container:

_LIT(KText,"MyLabel");
CQikScrollableContainer* container =
    LocateControlByUniqueHandle<CQikScrollableContainer>(EMyDetailViewScrollableContainerCtrl);

if(container != NULL)
    {
    CEikLabel* labelCtrl = new (ELeave) CEikLabel();
    container->AddControlLC(labelCtrl, EMyLabel);    //Do not push on Cleanup Stack before
    labelCtrl->ConstructL();
    labelCtrl->SetUniqueHandle(EMyLabel);
    labelCtrl->SetObserver(this);
    labelCtrl->SetTextL(KText);
    CleanupStack::Pop(labelCtrl);       
    }

Here, the control to add to an existing scrollable container is enclosed in a system building block:

CQikScrollableContainer* container =
    LocateControlByUniqueHandle<CQikScrollableContainer>(EMyDetailViewScrollableContainerCtrl);

if(container != NULL)
    {
    CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtCaptionedOnelineBuildingBlock);
        
    container->AddControlLC(block, EMyBuildingBlock);
    block->ConstructL();
    block->SetUniqueHandle(EMyBuildingBlock);
    block->SetDividerBelow(ETrue);
    _LIT(KCaptionText,"My Caption");
    block->SetCaptionL(KCaptionText, EQikItemSlot1); //the slot ID are defined in qikon.hrh
        
    // Create the Label and add it to the System Building Block
    _LIT(KMyLabelText, "My label text");
    CEikLabel* labelCtrl = new (ELeave) CEikLabel();
    block->AddControlLC(labelCtrl, EQikItemSlot2);
    labelCtrl->ConstructL();
    labelCtrl->SetUniqueHandle(EMyLabel);
    labelCtrl->SetObserver(this);
    labelCtrl->SetTextL(KMyLabelText);
    CleanupStack::Pop(labelCtrl);
    CleanupStack::Pop(block);         
    }

When you add a control that requires four-way navigation, it might be useful to add a Control Stand-in control for the control. The real control is then used in a Container Pop-out which pops out when the user acts on the Control Stand-in control.

CQikScrollableContainer* container = LocateControlByUniqueHandle<CQikScrollableContainer>(EMyDetailViewScrollableContainerCtrl);

if(container != NULL)
    {
    CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtCaptionedOnelineBuildingBlock);
        
    container->AddControlLC(block, EMyBuildingBlock);
    block->ConstructL();
    block->SetUniqueHandle(EMyBuildingBlock);
    block->SetDividerBelow(ETrue);
        
    _LIT(KCaptionText,"My Caption");
    block->SetCaptionL(KCaptionText, EQikItemSlot1); //the slot ID are defined in qikon.hrh
        
    // Create the Plain text editor and add it to the System Building Block.
    _LIT(KMyText, "My text");
        
    CEikEdwin* edwin = new (ELeave) CEikEdwin();
    CleanupStack::PushL(edwin);
        
    CQikControlStandIn* standIn = new(ELeave) CQikControlStandIn(edwin);
    CleanupStack::Pop(edwin);
        
    block->AddControlLC(standIn, EQikItemSlot2);
    standIn->ConstructL();
    standIn->SetUniqueHandle(EMyStandin);
        
    edwin->ConstructL();
    edwin->SetTextL(&KMyText);
    edwin->SetUniqueHandle(EMyEdwin);
        
    CleanupStack::Pop(standIn);
    CleanupStack::Pop(block);         
    }

Softkey style Pen style

Title bar with View context area in soft...

Title bar with View context area in softkey style (marked red). The view context bar shows no tabs. The view class inherits from the CQikViewBase class.

Title bar with View context area in pen...

Title bar with View context area in pen style (marked red). The view context bar shows no tabs. The view class inherits from the CQikViewBase class.

Application space in softkey style (mark...

Application space in softkey style (marked red).

Application space in pen style (marked r...

Application space in pen style (marked red).

Softkey style Pen style

Title bar with View context area in soft...

Title bar with View context area in softkey style (marked red). The view context bar shows a tab for each view. The view classes inherit from the CQikMultiPageViewBase class.

Title bar with View context area in pen...

Title bar with View context area in pen style (marked red). The view context bar shows a tab for each view. The view classes inherit from the CQikMultiPageViewBase class.

Application space in softkey style (mark...

Application space in softkey style (marked red).

Application space in pen style (marked r...

Application space in pen style (marked red).


5 Answers to some FAQ about migrating from UIQ 2 to UIQ 3

[Top]


6. Glossary

This is an explanation of some of the expressions used in this guide.

Expression/Abbreviation Description

CPF

Command Processing Framework

DNL

Direct Navigation Link

UI

User Interface

ID

Identity

UID

Unique ID (32 bit number used by EPOC)