Compound controls in traditional architecture

Compound controls are controls that contain other controls. To create a compound control, you must do the following:

  • construct the control in the parent control (main control that owns the window in which the child control appears). The control should be constructed in the constructor for the window. An example of an implementation is as follows:

    void CMyViewContainer::ConstructL(const TRect& aRect)
        {
        CreateWindowL();
    
        iLabel = new (ELeave) CEikLabel;
        iLabel->SetContainerWindowL( *this );
        iLabel->SetTextL( _L("MyView 1\n\nSelect local view\nswitching from menu") );
    
        SetRect(aRect);
        ActivateL();
        }

    , where

    iLabel = new (ELeave) CEikLabel; creates a CEikLabel object, which is a class that supports the display of text in the parent window.

    CCoeControl::SetContainerWindowL() makes the non-window-owning control a child of the window-owning control.

    CEikLabel::SetTextL() sets a text for the label

    The other methods are the standard methods for creating a window for the window-owning control.

  • add a method to the owning control that returns the number of controls in the compound control. An example of an implementation is as follows:

    TInt CMyViewAppContainer::CountComponentControls() const
        {
        return KNumberOfControls; // return nbr of controls inside this compound control
        }

    , where

    CMyViewAppContainer::CountComponentControls() overrides CCoeControl::CountComponentControls() to return the number of controls in the compound control

    KNumberOfControls is a TInt constant for the number of controls in the application. Other approaches could be used.

  • Add a method to the owning control that returns each of the controls by a zero-based index. An example of an implementation is as follows:

    CCoeControl* CContainerContainer::ComponentControl(
        TInt aIndex)  const
        {
            switch ( aIndex )
            {
            case 0:
                return iLabel; // return a pointer to the 
                                 //iLabel
            default:
                return NULL;
            }
        }
    

    , where

    CCoeControl* CContainerContainer::ComponentControl(TInt aIndex) gets an indexed component of a compound control. There are two ways to implement a compound control. One way is to override this function. The other way is to use the CCoeControlArray functionality (see the CCoeControl::InitComponentArrayL() method).

    Note: Within a compound control, each component control is identified by an index.

    All child controls should be accessible by CCoeControl::ComponentControl() at any time, regardless of whether they are visible or not. You can adjust the visibility of a control using the CCoeControl::MakeVisible() method.

CCoeControl* CContainerContainer::ComponentControl(TInt aIndex) and CCoeControl::CountComponentControls() work in conjunction with each other. The Symbian platform can query the control as to how many components it has and then request a pointer to each of the component's controls. Controls can be added or removed at run time using these two methods. The framework uses this information to draw the container.

The compound control usually owns the child controls and therefore it is responsible of their construction and destruction. The compound control should also set the positions and sizes of its child controls; it must ensure that all child controls are inside the compound control rectangle and visible child rectangles do not overlap each other.