UIQ Technology
Symbian OS Library

UIQ 3.1 SDK        UIQ developer portal

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



UIQ Controls - System Building Blocks


1. Introduction

This guide explains the UIQ control System Building Blocks (CQikBuildingBlock). A building block is a compound control used to layout the controls in a view. A view can consist of multiple building blocks. Each building block has a defined layout and a certain number of slots where controls or captions can be inserted.

UIQ provides a set of System Building Blocks that can be used by application developers. There are 18 System Building Blocks available.

If none of the System Building Blocks fits the purpose of the application developer, it is possible to create Custom Building Blocks. This should, however, only be a last resort when there is no System Building Block that suits the purpose.

The following functionality can be used by the application developer:

Default control configuration.

Examples of Building Block graphics

A Building Block is normally transparent.

A Building Block may have a divider at the bottom to visually separate information.

A Building Block is highlighted when it has focus.

A Building Block changes highlight while it is being tapped.

System Building Blocks Overview

OnelineBuildingBlock

IconCaptionedOnelineBuildingBlock

TwolineBuildingBlock

IconCaptionedTwolineBuildingBlock

ManylinesBuildingBlock

OnelineIconBuildingBlock

HalflineHalflineBuildingBlock

TwolineIconBuildingBlock

CaptionedHalflineBuildingBlock

IconOnelineIconBuildingBlock

CaptionedOnelineBuildingBlock

IconTwolineIconBuildingBlock

CaptionedTwolineBuildingBlock

IconIconOnelineBuildingBlock

IconOnelineBuildingBlock

MediumThumbnail-DoubleOnelineBuildingBlock

IconTwolineBuildingBlock

LargeThumbnailThreelineBuildingBlock


1.1 Further Reference

See the API documentation for System Building Blocks (CQikBuildingBlock).

An alternative to using System Building Blocks is to use Custom Building Blocks. See the How To guide for Custom Building Blocks.

See even the API documentation for Custom Building Blocks (CQikGenericBuildingBlock).

[Top]


2. Architecture

System Building Blocks inherits from CCoeControl.

High-level architecture of System Buildi...

High-level architecture of System Building Blocks

[Top]


3. Using the Control

This section explains how the control is constructed, used and destroyed. Source code examples are used and explained to illustrate how System Building Blocks are used.


3.1 Includes and Identifications

For the System Building Blocks use the following #include directive:

#include <QikBuildingBlock.h>

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

LIBRARY qikctl.lib

Use the following identifiers when specifying the different System Building Blocks in resource data files. The IDs are defined in QikStockControls.hrh, and they are used by the framework when constructing a System Building Block from resource data:

EQikCtOnelineBuildingBlock
EQikCtCaptionedTwolineBuildingBlock
EQikCtTwolineBuildingBlock
EQikCtManylinesBuildingBlock
EQikCtIconOnelineBuildingBlock
EQikCtIconCaptionedTwolineBuildingBlock
EQikCtIconTwolineBuildingBlock
EQikCtOnelineIconBuildingBlock
EQikCtIconOnelineIconBuildingBlock
EQikCtIconTwolineIconBuildingBlock
EQikCtMediumThumbnailDoubleOnelineBuildingBlock
EQikCtLargeThumbnailThreelineBuildingBlock
EQikCtCaptionedOnelineBuildingBlock
EQikCtIconCaptionedOnelineBuildingBlock
EQikCtTwolineIconBuildingBlock
EQikCtIconIconOnelineBuildingBlock
EQikCtHalflineHalflineBuildingBlock
EQikCtCaptionedHalflineBuildingBlock


3.2 Resource Structure

The resources to use are defined by the QIK_SYSTEM_BUILDING_BLOCK structure, which refers to one of the three structures QIK_SLOT_CONTENT, QIK_SLOT_CONTENT_DIRECT or QIK_SLOT_CONTENT_INDIRECT as defined in Qikon.rh. The structures look like this:

STRUCT QIK_SYSTEM_BUILDING_BLOCK
    {
    BYTE version = 2; //don't change
    LONG flags = 0;
    LTEXT default_caption = "";
    STRUCT content[]; //QIK_SLOT_CONTENT
    }

STRUCT QIK_SLOT_CONTENT
    {
    BYTE struct_type = 0; //do not change
    LONG slot_id = -1;
    LONG unique_handle = -1;
    LTEXT caption = "";
    }
                
STRUCT QIK_SLOT_CONTENT_DIRECT
    {
    BYTE struct_type = 2; //do not change
    LONG slot_id = -1;
    LONG unique_handle = -1;
    LONG type = -1;
    LONG itemflags = 0;
    STRUCT control;
    }
                
STRUCT QIK_SLOT_CONTENT_INDIRECT
    {
    BYTE struct_type = 1; //do not change
    LONG slot_id = -1;
    LONG unique_handle = -1;
    LONG type = -1;
    LONG itemflags = 0;
    LLINK control = -1;
    }

The values given in the structure definitions are default values. The QIK_SYSTEM_BUILDING_BLOCK structure contains the following:

The QIK_SLOT_CONTENT struct represents the content of a slot in a building block. It is referenced by QIK_SYSTEM_BUILDING_BLOCK. Use this struct when the content of the slot is a caption, or the control is included in the QIK_CONTROL_COLLECTION, or the control factory only needs the unique handle to create the control. The struct contains the following:

The QIK_SLOT_CONTENT_DIRECT struct represents the content of a slot in a building block. It is referenced by QIK_SYSTEM_BUILDING_BLOCK. Use this struct when you do not want to use a QIK_CONTROL_COLLECTION, and you want to specify the control's resource inline. The struct contains the following:

The QIK_SLOT_CONTENT_INDIRECT struct represents the content of a slot in a building block. It is referenced by QIK_SYSTEM_BUILDING_BLOCK. Use this struct when you do not want to use a QIK_CONTROL_COLLECTION, and you want to reference the resource struct of the control through a link, or if you do not want to create the control using resources. The struct contains the following:

The System Building Blocks can have the following flags:

Generic Building Blocks - Resource flags

EQikBuildingBlockDividerBelow

A one-pixel thick divider line is drawn below the building block. This divider is used to provide a visual cue to the user of which information belongs together.

EQikBuildingBlockMirror

Mirroring is turned on.

EQikBuildingBlockNoMirroring

Mirroring is turned off.

EQikBuildingBlockDebugMode

Used when you want to see the extent of the building blocks and their slots while you are developing.


3.3 Construction

This section discusses three different ways of constructing controls. It describes how to construct and add a control to the view of an application. The view framework is used in all three cases but in three different ways.

A common way to construct controls is to specify them in the resource files and then let the framework construct them from there. Specifying the controls in resource files is the preferred way of constructing controls since it allows for easier modifications compared to creating them entirely from source code.

This section covers different ways of constructing System Building Blocks.

3.3.1 Construction of a System Building Block, with View Framework Using Data from a Resource File

The example below describes how to construct a System Building Block, containing a Label control, using the view framework.

The reason the example seems to be rather complex is because it demonstrates how to construct a complete view containing a Scrollable Container and a Layout Manager. It encapsulates a Label control in a System Building Block. The view supports both pen and softkey styles; support of both styles in a view is optional.

1) Declare an enumeration for the System Building Block and for the Label control to be used in the view in a *.hrh file. Hrh files are files to be included both in resource files (*.rss) and C++ files:

/* Declare the controls' ID in a *.hrh file for use both in resource and cpp */
enum TMyViewControls
    {
    EMyViewScrollableContainer,
    EMyViewBuildingBlock,
    EMyViewLabel,
    EMyViewNumberOfControls
    };

2) Declare the control to be used in the view in your resource (*.rss) file:

/* Declare the set of the System Building Block to be used in the view */
RESOURCE QIK_CONTROL_COLLECTION r_my_view_controls
    {
    items =
        {
        QIK_CONTROL
            {
            unique_handle = EMyViewScrollableContainer;
            type = EQikCtScrollableContainer;
            control = r_my_scroll_pane;
            },
        QIK_CONTROL
            {
            unique_handle = EMyViewLabel;
            type = EEikCtLabel;
            control = r_my_label;
            },
        QIK_CONTROL
            {
            unique_handle = EMyViewBuildingBlock;
            type = EQikCtCaptionedTwolineBuildingBlock;
            control = r_my_building_block;
            }
        };
    }

3) Define the view and its contents in your resource file:

/* The view */
RESOURCE QIK_VIEW r_my_view
    {
    pages = r_my_viewpages;
    }
            
/* The view page */
RESOURCE QIK_VIEW_PAGES r_my_viewpages
    {
    pages =
        {
        QIK_VIEW_PAGE
            {
            container_unique_handle = EMyViewScrollableContainer;
            page_content = r_my_view_container_details;
            }
        };
    }

4) Define the resource for the Scrollable Container used in the view:

/* The scrollable container used in the view */
RESOURCE QIK_SCROLLABLE_CONTAINER r_my_scroll_pane
    {
    }

5) Declare the contents and properties for the Scrollable Container used in the view:

/* Contents of the Scrollable Container used in the view */
RESOURCE QIK_SCROLLABLE_CONTAINER_SETTINGS r_my_view_container_details
    {
    controls =
        {
        QIK_CONTAINER_ITEM
            {
            unique_handle = EMyViewBuildingBlock;
            }
        };
    }

6) Define the control resource struct contained in the System Building Block:

/* The Label used in the view */
RESOURCE LABEL r_my_label
    {
    txt="This will show a Label control in a captioned two-line Building Block";
    }

7) Define the settings for the System Building Block containing the control:

/* Settings for the EQikCtCaptionedTwolineBuildingBlock containing the System Building Blocks */
RESOURCE QIK_SYSTEM_BUILDING_BLOCK r_my_building_block
    {
    content =
        {
        QIK_SLOT_CONTENT
            {
            slot_id = EQikItemSlot1;
            caption = "CaptionedTwoLinedBB:";
            },
        QIK_SLOT_CONTENT
            {
            slot_id = EQikItemSlot2;
            unique_handle = EMyViewLabel;
            }
        };
    }

8) The configurations of the view:

RESOURCE QIK_VIEW_CONFIGURATIONS r_singlepageview_configurations
    {
    configurations=
        {
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            view = r_view_softkey_style_multi;
            command_list = r_commands_task_menu;
            },
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikPenStyleTouchPortrait;
            view = r_view_softkey_style_multi;
            command_list = r_commands_task_menu;
            }
        };
    }

9) The view framework constructs the view described in this example with this code:

void CMySinglePageView::ViewConstructL()
    {
    ViewConstructFromResourceL( R_SINGLEPAGEVIEW_CONFIGURATIONS, R_MY_VIEW_CONTROLS);
    }

10) The result should look something like this:

3.3.2 Construction with Your Own C++ Code Using Data from a Resource File

The example below describes how to construct a System Building Block from resource with your own C++ code.

The reason the example seems to be rather complex is because it demonstrates how to construct a complete view containing a Scrollable Container and a Layout Manager. It encapsulates a Label control in the System Building Block.

This example uses the resource structs from the previous example. The following code creates a System Building Block:

#include <eiklabel.h>
#include <QikRowLayoutManager.h>
#include <QikGridLayoutManager.h>
#include <QikBuildingBlock.h>
                    
void CMySinglePageView::ViewConstructL()
    {
                    
    // Give a layout manager to the view
    CQikGridLayoutManager* gl = CQikGridLayoutManager::NewLC();
    SetLayoutManagerL(gl);
    CleanupStack::Pop(gl);
                
    // Create a container and give it to the view
    ControlProvider()->ControlInfos().AddFromResourceL(R_MY_VIEW_CONTROLS);
    CCoeControl* ctrl = ControlProvider()->ControlConstructIfNeededL(EMyViewScrollableContainer, *this);
    ASSERT(ctrl);
    CQikContainerBase* container;
    ctrl->MopGetObjectNoChaining(container);
    ASSERT(container);
    Controls().AppendLC(container);
    CleanupStack::Pop(ctrl);
                    
    // Create a layout manager to be used inside the container
    CQikRowLayoutManager* rowlayout = CQikRowLayoutManager::NewLC();
    container->SetLayoutManagerL(rowlayout);
    CleanupStack::Pop(rowlayout);
                
    // Create a two-line captioned System Building Block (containing a Label) and add it to the container
    CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtCaptionedTwolineBuildingBlock);
    container->AddControlLC(block, EMyViewBuildingBlock);
        
    TResourceReader blockReader;
    iCoeEnv->CreateResourceReaderLC(blockReader,R_MY_BUILDING_BLOCK);
    block->ConstructFromResourceL(blockReader, *ControlProvider());
    block->SetUniqueHandle(EMyViewBuildingBlock);
    CleanupStack::PopAndDestroy(); //blockReader
    CleanupStack::Pop(block);
    }

What the code does

1) Initializes the Command Manager with an empty Command List. The controls placed in the view add their commands to the Command List when they receive focus.

2) Creates a Layout Manager for the view. The Grid Layout Manager fills the view with its only control in this example, the Scrollable Container.

3) Loads the control collection R_MY_VIEW_CONTROLS into the Control Provider. Then the Control Provider is asked to create the Scrollable Container.

4) Uses the MopGetObjectNoChaining function to determine whether the control that was created really is a class of the type CQikContainerBase before it is added to the view.

5) Creates a Layout Manager to control the layout inside the container. Adds the Layout Manager to the container.

6) Constructs the System Building Block from the resource R_MY_BUILDING_BLOCK. Adds the Building Block to the container.

Use AddControlLC to add the System Building Block to a Scrollable Container. Add the controls as soon as they are created. Do not push them onto the Cleanup Stack before they are added. Do not pop them from the Cleanup Stack until they are fully constructed. A TCleanupItem created in AddControlLC will make sure that the control is both cleaned up and removed from the Components Array if a leave occurs before the control is fully constructed.

3.3.3 Construction Solely from C++ Code

The example below describes how to construct a System Building Block solely from C++ code.

The reason the example seems to be rather complex is because it demonstrates how to construct a complete view also containing a Scrollable Container and a Layout Manager. It also constructs a Label control to be contained in the System Building Block.

#include <EikLabel.h>
#include <QikScrollableContainer.h>
#include <QikRowLayoutManager.h>
#include <QikGridLayoutManager.h>
#include <QikBuildingBlock.h>
                    
void CMySinglePageView::ViewConstructL()
    {
                    
    // Give a layout manager to the view
    CQikGridLayoutManager* gridlayout = QikGridLayoutManager::NewLC();
    SetLayoutManagerL(gridlayout);
    CleanupStack::Pop(gridlayout);
                        
    // Create a container and add it to the view
    CQikScrollableContainer* container = new (ELeave) CQikScrollableContainer();
    Controls().AppendLC(container);
    container->ConstructL(EFalse);
    CleanupStack::Pop(container);
                        
    // Create a layout manager to be used inside the container
    CQikRowLayoutManager* rowlayout = CQikRowLayoutManager::NewLC();
    container->SetLayoutManagerL(rowlayout);
    CleanupStack::Pop(rowlayout);
                    
    // Create the System Building Block and set the caption.
    CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtCaptionedTwolineBuildingBlock);
    container->AddControlLC(block, EMyViewBuildingBlock);
    block->ConstructL();
    block->SetUniqueHandle(EMyViewBuildingBlock);
    block->SetDividerBelow(ETrue);
    block->SetCaptionL(_L(“Caption”), EQikItemSlot1); //the slot ids are defined in qikon.hrh

    // Create the Label and add it to the System Building Block
    _LIT(myText, "a Label text");
    CEikLabel* label = new (ELeave) CEikLabel();
    block->AddControlLC(label, EQikItemSlot2);
    label->SetUniqueHandle(EMyViewLabel);
    label->SetObserver(this);
    label->SetTextL(myText);
    CleanupStack::Pop(label);
    CleanupStack::Pop(block);
    }

What the code does

1) Initializes the Command Manager with an empty Command List. The controls placed in the view add their commands to the Command List when they receive focus.

2) Creates a Layout Manager for the view. The Grid Layout Manager fills the view with its only control in this example, the Scrollable Container.

3) Instantiates a container and adds it to the view.

4) Creates a Layout Manager and adds it to the container.

5) Creates a System Building Block control from C++ code.

6) Creates a Label control from C++ code. Adds the Label control to the System Building Block. Sets the view, this, to be an observer of the Label. The view's base class, CQikViewBase, handles focus changes in its method HandleControlEventL. For more details see the section below on how to be notified with Control Events.

3.3.4 Construction with the Dialog Framework Using Data from a Resource File

Not applicable.


3.4 Using the System Building Blocks

This section covers the most common functions used for interacting with the control.

When constructing the control with resource data, no reference to the control is available in the view class. When constructing the control with code, the preferred way might be to not save a reference to the control. In both these cases, the LocateControlByUniqueHandle function is used to get a pointer to the control by supplying the control's unique handle. When constructing the view and the control from code, you must explicitly set this unique handle by calling the method SetUniqueHandle. See the code examples below.

Note that the function will return NULL if the control could not be found. Always check the pointer before using it!

// Set the unique handle
block->SetUniqueHandle(EMyViewBuildingBlock);
            
// Get a pointer to the edwin control
CQikBuildingBlock* block = LocateControlByUniqueHandle<CQikBuildingBlock>(EMyViewBuildingBlock)

3.4.1 How to Create a System Building Block with a Direct Reference to a Control, Using Data from a Resource File

The example in the section "Construction of a System Building Block with View Framework Using Data from Resource File" shows how to construct a System Building Block using the QIK_SLOT_CONTENT struct. This example shows how to construct a System Building Block using the QIK_SLOT_CONTENT_DIRECT struct. Use this struct when you:

RESOURCE QIK_SYSTEM_BUILDING_BLOCK r_captioned_oneline_building_block_direct
    {
    flags=EQikBuildingBlockDividerBelow
    content =
        {
        QIK_SLOT_CONTENT_DIRECT
            {
            slot_id = EQikItemSlot1;
            type = EEikCtLabel;
            control=LABEL
                {
                txt="a System Building Block with direct reference to a Label control.";
                };
            }
        };
    }

To actually create the System Building Block, use the example in the section about construction solely from C++ Code and replace the two last code sections, from the "Create the System Building Block and..." comment, with the code below:

CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtOnelineBuildingBlock);
container->AddControlLC(block,EMyViewBuildingBlock);
                        
TResourceReader reader;
iCoeEnv->CreateResourceReaderLC(reader, R_CAPTIONED_TWOLINE_BUILDING_BLOCK_DIRECT);
block->ConstructFromResourceL(reader, *ControlProvider());
block->SetUniqueHandle(EMyViewBuildingBlock);
CleanupStack::PopAndDestroy(); //reader

CleanupStack::Pop(block);

3.4.2 How to Create a System Building Block with an Indirect Reference to a Control, Using Data from a Resource File

The example in the section "Construction of a System Building Block, with View Framework Using Data from a Resource File", shows how to construct a System Building Block using the QIK_SLOT_CONTENT struct. This example shows how to construct a System Building Block using the QIK_SLOT_CONTENT_INDIRECT struct. Use this struct when you:

RESOURCE QIK_SYSTEM_BUILDING_BLOCK r_captioned_oneline_building_block_indirect
    {
    flags=EQikBuildingBlockDividerBelow;
    content =
        {
        QIK_SLOT_CONTENT_INDIRECT
            {
            slot_id = EQikItemSlot1;
            type = EEikCtLabel;
            control= r_my_label;
            }
        };
    }
                
RESOURCE LABEL r_my_label
    {
    txt = "a System Building Block with indirect reference to a Label control.";
    }

To actually create the System Building Block, use the example in the section "Construction Solely from C++ Code" and replace the two last code sections, from the "Create the System Building Block and..." comment, with the code below:

CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtOnelineBuildingBlock);
container->AddControlLC(block,EMyViewBuildingBlock);
                        
TResourceReader reader;
iCoeEnv->CreateResourceReaderLC(reader, R_CAPTIONED_TWOLINE_BUILDING_BLOCK_INDIRECT);
block->ConstructFromResourceL(reader, *ControlProvider());
block->SetUniqueHandle(EMyViewBuildingBlock);
CleanupStack::PopAndDestroy(); //reader
                    
CleanupStack::Pop(block);

3.4.3 How to be Notified with Control Events

In order to be notified when a System Building Block changes state you must add an observer to the System Building Block. An observer is an object of the type MCoeControlObserver. The observer receives a function call to its function HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType) when the System Building Block changes state.

The view base class, CQikViewBase, implements the MCoeControlObserver. The HandleControlEventL function must be overloaded in the view class because the view inherits from CQikViewBase.

The following source code example shows how to add an object as an observer and how to receive events from the System Building Block:

void CMySinglePageView::ViewConstructL()
    {
    // Construction code
    …
    // Adding this object as an observer
    block->SetObserver(this);
    }

void CMySinglePageView::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType)
    {
    // Call base class to handle focus management
    CQikViewBase::HandleControlEventL(aControl, aEventType);
                
    CQikBuildingBlock* block = LocateControlByUniqueHandle<CQikBuildingBlock>(EMyViewBuildingBlock);
                
    if(aControl == block)
        {
        switch(aEventType)
            {
            case EEventStateChanged:
                // The internal state of the System Bulilding Block was changed,
                // for example, due to another item being selected. 
                break;          
                                    
            case EEventRequestExit:
                break;
                                    
            case EEventRequestCancel:
                break;
                                    
            case EEventRequestFocus:
                // The control received a pointer down event
                break;
                                    
            case EEventPrepareFocusTransition:
                // A focus change is about to appear
                break;
                                
            case EEventInteractionRefused:
                // The control is dimmed and received a
                // pointer down event.
                break;
                        
            default:
                break;
            }           
        }
    }

The reason for calling the base class's HandleControlEventL function is that the view base class, CQikViewBase, handles focus management between controls in the view. If the control's observer is not a class which derives from CQikViewBase, focus management must be resolved by the observer itself. If a control requests focus and does not get it from the observer, it will generate a panic in some cases if the observer does not leave.

For more details on the TCoeEvent type, see class MCoeControlObserver in the API documentation.


3.5 Destruction

Destroying the control is just a matter of invoking operator delete on the System Building Block object.

[Top]


4. Subclassing

If you want customize a Building Block, you could subclass System Building Blocks, but it is better to use Custom Building Blocks. Creating a Custom Building Block should, however, only be a last resort when there is no System Building Block that fits your needs.

[Top]


5. Glossary

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

Expression Meaning

Compound control

A control containing other controls.

Slot

A slot is an area within a building block where one control can be placed.

Divider

A visual cue to indicate separate types of information.

unique_handle

A identifier for the control that is unique within the view.