UIQ Technology
Symbian OS Library

UIQ 3.1 SDK        UIQ developer portal

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



UI configuration compatibility


Introduction

There are a number of issues worth considering when writing an application that is intended to work on phones with different UI configurations. In order to minimize the need for testing on many phones and with various UI configurations on the emulator, there are a number of guidelines, outlined in this section, to follow. Most of the problems that might occur are related to commands: they are shown in the wrong way, appear when they should not or are missing when they should be present. If you follow the guidelines in this guide most of those problems should never occur. However, some testing on different phones and UI configurations will probably be needed to make sure everything works as expected.


Command type

The most important parameter to set correctly is the command type. Study the table in section 3.4.1, Placement, in the Programmer's Guide to New Features in UIQ 3 to see how commands are distributed on softkeys as opposed to distribution in the application menu and the Button bar.

[Top]


One or multiple command lists


In applications - command owners

An application can either have different command lists for each UI configuration the application is written for, that is, different QIK_COMMAND_LISTs for each QIK_VIEW_CONFIGURATION, or it could in some cases use just one QIK_COMMAND_LIST for all UI configurations. Which path to choose is basically a matter of taste, but if it is possible to have just one command list, then it is probably the solution that is less error prone and easier to maintain. It is generally easier with one command list, but using multiple command lists provides more control; you can have different sets of commands, different strings, different groups and so forth.

Here is an example of commands for a view as they would appear on the screen in different UI configurations:

Pen-style UI configuration Softkey-style UI configuration

New

New

Delete

Delete

Open

More

More

It is quite common that the commands for different UI configurations are very similar, as in this example. Instead of creating two separate command lists, however, you can have just one list but flag "Open" like this:

QIK_COMMAND
    {
    id = EMyCommandOpen;
    type = EQikCommandTypeScreen;
    text = STRING_r_my_cmd_open;
    cpfFlags = EQikCpfFlagInteractionSoftkeysOnly;
    }

There are a number of different flags that can be used to define which UI configuration parameter the command must match in order to be displayed.

When the structure of the command lists is different, for example, when some commands are part of a named group in one list but not in the other, it is probably better to make two different lists.

Here is another example showing the difference between one and multiple command lists:

RESOURCE QIK_VIEW_CONFIGURATIONS r_my_configurations
    {
    configurations =
        {
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikPenStyleTouchPortrait;
            command_list=r_my_commands_menu;
            },
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            command_list=r_my_commands_softkey;
            }
        };
    }

RESOURCE QIK_COMMAND_LIST r_my_commands_menu
    {
    items=
        {
        QIK_COMMAND
            {
            id=EMyCmdDone;
            type=EQikCommandTypeDone;
            text=STRING_r_my_cmd_done;
            }
        };
    }

RESOURCE QIK_COMMAND_LIST r_my_commands_softkey
    {
    items=
        {
        QIK_COMMAND
            {
            id=EMyCmdDone;
            type=EQikCommandTypeDone;
            text=STRING_r_my_cmd_done;
            },
        QIK_COMMAND
            {
            id=EMyCmdCancel;
            type=EQikCommandTypeCancel;
            text=STRING_r_my_cmd_cancel;
            },
        QIK_COMMAND
            {
            id=EMyCmdDelete;
            type=EQikCommandTypeDelete;
            text=STRING_r_my_cmd_delete;
            }
        };
    }

This is arguably more conveniently written as:

RESOURCE QIK_VIEW_CONFIGURATIONS r_my_configurations
    {
    configurations =
        {
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikPenStyleTouchPortrait;
            command_list=r_my_commands;
            },
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            command_list=r_my_commands;
            }
        };
    }

RESOURCE QIK_COMMAND_LIST r_my_commands
    {
    items=
        {
        QIK_COMMAND
            {
            id=EMyCmdDone;
            type=EQikCommandTypeDone;
            text=STRING_r_my_cmd_done;
            },
        QIK_COMMAND
            {
            id=EMyCmdCancel;
            type=EQikCommandTypeCancel;
            text=STRING_r_my_cmd_cancel;
            cpfFlags=EQikCpfFlagInteractionSoftkeysOnly;
            },
        QIK_COMMAND
            {
            id=EMyCmdDelete;
            type=EQikCommandTypeDelete;
            text=STRING_r_my_cmd_delete;
            cpfFlags=EQikCpfFlagInteractionSoftkeysOnly;
            }
        };
    }


In controls - command adders

The rules and guidelines regarding one or multiple command lists for applications apply in general to controls as well. However, there are two major differences.

The first difference is that applications have framework support for selecting and switching command lists when the UI configuration changes. If a control wants to have multiple command lists it needs to select the command list, either by using the downgrade path or by checking UI configuration parameters, and then react to changes in the UI configuration.

The other difference is that command model owners know the command lists which are available and whether one or multiple command lists have been created. Command adders do not have this information.

It is generally easier and less error prone to use just one command list for controls, but by using multiple lists you have more control.

[Top]


Downgrade path

If a model owner has not specified a command list that exactly matches the UI configuration of the phone it gets a call to FindCompatibleUiConfig() where it chooses the closest fit. Views, View-dialogs, and simple dialogs all have the same downgrade path, that is, they use the same algorithm to make this choice: QikUiConfigUtils::FindCompatibleUiConfigMode().

The system default downgrade path values matching screen modes highest, followed by interaction styles, touchscreens and orientations. However, you cannot rely on any specific prioritization of the different parameters since it might differ between different UI configurations and phones.

An example: you have specified different command lists and layouts for a view in Pen style and Softkey style. When you run that view on another UI configuration, such as Softkey style Touch, the downgrade path will be used to select the closest match, which happens to be Pen style. If you do not agree with the choice of the downgrade path you can easily add Softkey style Touch to the list of supported UI configurations of the view and manually choose which commands and layout to use.

There are several situations where you want to make choices depending on the UI configuration of the phone, such as implementing FindCompatibleUiConfig(), choosing which set of commands to use, launching different dialogs, or choosing between different strings. You could either check UI parameters manually or use the system downgrade path, which is preferable, like this:

RArray<TInt> array;
CleanupClosePushL(array);

array.AppendL(KQikSoftkeyStylePortrait);
array.AppendL(KQikSoftkeyStyleSmallPortrait);
array.AppendL(KQikPenStyleTouchLandscape);
array.AppendL(KQikSoftkeyStyleTouchPortrait);

const TInt index = QikUiConfigUtils::FindCompatibleUiConfigMode(array);

CleanupStack::PopAndDestroy(); //array

Or alternatively:

const TInt resource = QikUiConfigUtils::FindCompatibleResource(R_DIALOG_CONFIGS);
CEikDialog* dialog = new(ELeave) CEikDialog;
dialog->ExecuteLD(resource);

RESOURCE ARRAY r_dialog_configs
    {
    items =
        {
        QIK_UI_CONFIG_RESOURCE
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            resource = r_softkey_dialog;
            },
        QIK_UI_CONFIG_RESOURCE
            {
            ui_config_mode = KQikSoftkeyStyleSmallPortrait;
            resource = r_softkey_small_dialog;
            },
        QIK_UI_CONFIG_RESOURCE
            {
            ui_config_mode = KQikPenStyleTouchLandscape;
            resource = r_pen_landscape_dialog;
            },
        QIK_UI_CONFIG_RESOURCE
            {
            ui_config_mode = KQikSoftkeyStyleTouchPortrait;
            resource = r_softkey_touch_dialog;
            }
        };
    }

[Top]


Application assumptions

You should not make assumptions about which command list is currently loaded. The downgrade path might have selected another command list than the one you assume.

For example, if you have an application with two command lists: R_MY_MENUBAR_COMMANDS and R_MY_SOFTKEY_COMMANDS, this is wrong to assume that the appearance of an attribute in itself can tell you which command list is being used.

THIS ASSUMPTION IS WRONG:

if(uiConfigClient.CurrentConfig().InteractionStyle() == EQikInteractionStyleMenubar)
    {
    //do something that assumes that R_MY_MENUBAR_COMMANDS is the active command list
    }

Instead you should check to see if the command list is active.

THIS IS CORRECT, NO ASSUMPTION IS MADE:

if(/*CQikViewBase::*/IsCommandListActive(R_MY_MENUBAR_COMMANDS))
    {
    //do something that assumes that R_MY_MENUBAR_COMMANDS is the active command list
    }

Command adders can just as well check if any one of their QIK_COMMAND_LISTs is loaded by using CQikCommandManager::IsCommandListActive() directly.

[Top]


UI configuration parameters

A mistake when you want to have different behavior for different UI configurations of the phone is to check for the whole style.

THIS IS A MISTAKE:

if(CQUiConfigClient::Static().CurrentConfig() == KQikSoftkeyStyleLandscape)
    //do something

By doing so, the code is too dependent on the UI configuration of the phone. The code should, for example, probably not distinguish between the screen modes KQikSoftkeyStyleLandscape and KQikSoftkeyStyleLandscape180. Instead, using the significant UI configuration parameters is a better approach, if you do not want to use the downgrade path.

THIS IS CORRECT:

if(CQUiConfigClient::Static().CurrentConfig().ScreenMode() == EQikScreenModeLandscape)
    //do something

The four available parameters are:

Besides checking the parameters programmatically you can also flag a command to only be present for some value of a parameter:

The parameters that are tricky to get right are the touchscreen parameters and the UI-Interaction-style parameters. Probably the main reason that these are tricky is because they are not truly independent parameters; Softkey style is designed for non-touchscreen use and Pen style is designed for touchscreen use. Therefore, softkey-style design decisions correlate with non-touchscreen design decisions and pen-style design decisions correlate with touchscreen design decisions.

Some examples for when the touchscreen parameter should be used are:

Here is an example where UI-Interaction style is checked for text input commands.

THIS IS THE WRONG WAY:

if(CQUiConfigClient::Static().CurrentConfig().InteractionStyle() == EQikInteractionStyleSoftkey)
    CQikCommandManager::Static().InsertIntoCommandListL(*this, *this, R_MY_TEXT_INPUT_COMMANDS_SOFTKEY_STYLE);  
else
    CQikCommandManager::Static().InsertIntoCommandListL(*this, *this, R_MY_TEXT_INPUT_COMMANDS_PEN_STYLE);

But where a touchscreen should be used, for example if we want to use the pen to select text instead of using the Cut word and Copy word commands, we can check for the parameter directly.

THIS IS THE RIGHT WAY:

if(CQUiConfigClient::Static().CurrentConfig().TouchScreen() == EQikTouchScreenYes)
    CQikCommandManager::Static().InsertIntoCommandListL(*this, *this, R_MY_TEXT_INPUT_COMMANDS_TOUCHSCREEN_YES);    
else
    CQikCommandManager::Static().InsertIntoCommandListL(*this, *this, R_MY_TEXT_INPUT_COMMANDS_TOUCHSCREEN_NO);

[Top]


Adding commands

When you have multiple command lists there are two different ways to add commands. The commands could either be added to all command lists, which is the recommended way,

const TBool touchscreen = (CQUiConfigClient::Static().CurrentConfig().TouchScreen() == EQikUiConfigTouchScreenYes);
cmdManager.InsertIntoCommandListL(*this, *this, (touchscreen ? R_MY_TOUCHSCREEN_COMMANDS : R_MY_NON_TOUCHSCREEN_COMMANDS));

or they could be added to those command lists which match a certain UI-configuration parameter.

cmdManager.InsertIntoCommandListL(*this, *this, R_MY_TOUCHSCREEN_COMMANDS, EQikUiConfigTouchScreenYes);
cmdManager.InsertIntoCommandListL(*this, *this, R_MY_NON_TOUCHSCREEN_COMMANDS, EQikUiConfigTouchScreenNo);

When you have only one command list, you do not have to choose; you use the first option, that is, to add to all the command lists, which in this case is just one list.

[Top]


Setting command state

The same guidelines apply for setting the state of commands as for adding commands.

SetAvailable(), or the state flag EQikCmdFlagUnavailable, should be used in preference to SetDimmed()/SetInvisible() in most cases where you want to indicate that a command is not available to the user. If a command is unavailable, it will be invisible when the interaction style is softkey, and dimmed when the interaction style is menu bar.

[Top]


Commands duplicated in the UI

There are a number of cases when you want a command to be duplicated, such as on the button bar and in the application menu, on the left softkey and in the More menu, on a hardware key and in the More menu or in the application menu. One way to handle these cases is to duplicate the command in the command list, but that is not recommended since when you run that application on an unknown phone you might, for example, end up with duplicated commands in the More menu.

Most of these cases can be addressed by flagging the command to be duplicated in menu panes (application menu, dialog menu, more menu/right softkey, container pop-out menu, full screen floating menu):

QIK_COMMAND
    {
    id = EMyCommandNew;
    type = EQikCommandTypeScreen;
    text = "New";
    cpfFlags = EQikCpfFlagPreferToBePlacedInButtonbar | EQikCpfFlagDuplicateInMenuPane;
    }

[Top]


Hardware key commands

There are some recommendations and requirements as to which hardware keys a UIQ phone should have. But basically, you have to consider what would happen to your application if a phone did not have all of the hardware keys you expected it to have.

One example is a Select command in a list box. You want the command to be attached to the Action key on a Pen-style phone, and on the center softkey on a Softkey-style phone. But if there is a phone that does not have an Action key, the command would appear in the menu on a Pen-style phone; this you do not want because it is more convenient to use the touchscreen for selecting items.

If you want a command to only be present on a hardware key, that is, not even on a softkey, you can do this:

QIK_COMMAND
    {
    id = EMyCommandHardwareCommand;
    type = EQikCommandTypeItem;
    cpfFlags = EQikCpfFlagHardwarekeyOnly;
    }

Another aspect is how to treat commands you want to appear in the UI even if the hardware key they were expecting to be placed on should be omitted from a phone. Commands that are intended exclusively for hardware keys do not need any form of visual representation. But the expected hardware key may not be available, so it is a good idea to set a text label, a short text label or an icon for the command just in case.

Not setting at least one form of visual representation for a command has the same effect as flagging it EQikCpfFlagHardwarekeyOnly. If there is no hardware key, the command will not appear in the UI at all.

For example, if you run an application written for a Pen-style phone on a Softkey-style phone, commands intended for the Action key and other hardware keys might end up on softkeys and in the More menu; running a Softkey-style application on a Pen-style phone might move commands from hardware keys to the Button bar and the application menu.

[Top]


Button bar popouts

When you want a menu popout in the Button bar you just need to create a named group and make it end up on the Button bar. The problem with trying to make your own menu popout, for example having a command which ends up in the button bar and manually create a popout when the command is executed, is that it is difficult to find a solution that works if that application is run on a phone that does not use the Button bar.

QIK_COMMAND
    {
    id = EMyCommandNewGroup;
    type = EQikCommandTypeScreen;
    text = "New...";
    namedGroupLinkId = EMyCommandGroupLinkIdNew;
    cpfFlags = EQikCpfFlagPreferToBePlacedInButtonbar;
    },
    QIK_COMMAND
        {
        id = EMyCommandNewHouse;
        type = EQikCommandTypeScreen;
        text = "New house";
        namedGroupId = EMyCommandGroupLinkIdNew;
        },
    QIK_COMMAND
        {
        id = EMyCommandNewBoat;
        type = EQikCommandTypeScreen;
        text = "New boat";
        namedGroupId = EMyCommandGroupLinkIdNew;
        }