|
|
|||
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:
Set the caption in any of the slots,
Set the control in any of the slots,
Accessing the controls and captions,
Set the way the building block handles mirroring, that is, forcing no mirroring, forcing mirroring or following the application language,
Set a divider that is displayed below the building block,
Set the control to be able to gain focus or not.
Default control configuration.
The slots' default settings depend on the specific System Building Block. See System Building Block overview below for the default settings for the slots.
By default, the following configuration applies to a System Building Block:
It follows the mirroring of the application language,
It has no divider,
The control cannot gain focus.
By default, the following configuration applies to caption labels:
Normal system font is used,
Text emphasis is not used,
Text underlining is not used,
Text strikethrough is not used.
Default configuration for a specific control depends on the control itself.
Examples of Building Block graphics
|
System Building Blocks Overview
|
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).
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.
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
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:
version is always 2 and cannot be changed,
flags is used to customize the control and the available flags are defined in qikon.hrh and listed below,
default_caption is the default caption of the System Building Block,
content is a struct of type QIK_SLOT_CONTENT, QIK_SLOT_CONTENT_DIRECT or QIK_SLOT_CONTENT_INDIRECT.
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:
struct_type is the type of the struct, is always 0 and cannot be changed,
slot_id, the ID of the slot, is mandatory and depends on which building block is used, but values are usually taken from TQikBuildingBlockSlots as defined in Qikon.hrh,
unique_handle, the ID of the control, is mandatory if no caption is specified, is unique within the view and is used to reference a specific QIK_CONTROL in the control collection, or to tell a control factory which control to create,
caption is the caption of the slot and is mandatory if no control is specified.
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:
struct_type, the type of the struct, is always 2 and cannot be changed,
slot_id, the ID of the slot, is mandatory and depends on which building block is used, but values are usually taken from TQikBuildingBlockSlots as defined in Qikon.hrh,
unique_handle, the ID of the control, is optional, is unique within the view and is used to set the control's UniqueHandle() and send it to the control factories,
type, the control type, such as the items in TQikStockControls as defined in QikStockControls.hrh, is mandatory,
itemflags, the optional flags from TQikCtrlItemFlags as defined in Qikon.hrh, control the creation of the control,
control, which is mandatory, is the resource struct that is read by the control's ConstructFromResourceL(), such as QIK_SLIDER for EQikCtSlider.
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:
struct_type, the type of the struct, is always 1 and cannot be changed,
slot_id, the ID of the slot, is mandatory and depends on which building block is used, but values are usually taken from TQikBuildingBlockSlots as defined in Qikon.hrh,
unique_handle, the ID of the control, is optional, is unique within the view and is used to set the control's UniqueHandle() and send it to the control factories,
type, the control type, such as the items in TQikStockControls as defined in QikStockControls.hrh, is mandatory for controls created entirely from resource files, otherwise it depends on the control factories,
itemflags, the optional flags from TQikCtrlItemFlags as defined in Qikon.hrh, control the creation of the control,
control, which is mandatory for controls created entirely from resource files, otherwise it depends on the control factories, is the resource struct that is read by the control's ConstructFromResourceL(), such as QIK_SLIDER for EQikCtSlider.
The System Building Blocks can have the following flags:
|
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.
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:
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.
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.
Not applicable.
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)
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:
Do not want to use a QIK_CONTROL_COLLECTION.
Want to specify the control's resource inline.
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);
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:
Do not want to use a QIK_CONTROL_COLLECTION, and
want to reference the resource struct of the control through a link, or
Do no want to create the control using resources.
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);
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.
Destroying the control is just a matter of invoking operator delete on the System Building Block object.
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.
This is an explanation of some of the expressions used in this guide.
|