Join Now

Hi, I'm Paul, but you can also call me Todd and I won't get upset.

Creating a message details dialog - the implementation

Paul.Todd | 07 January, 2007 16:41

As I outlined in the previous posting we will now cover the implementation of the message detail dialog

Basically what we want to do is create a popup list that contains a listbox. The class is the CAknPopupList
which is a control that looks like a dialog box but contains a listbox.

Before we can create the popup list however we need to create a listbox, and this listbox is one of the
standard AVKON listboxes, in particular, CAknSingleHeadingPopupMenuStyleListBox. This listbox takes a
heading in the first column and the text in the second column. The text is also bold in the second
column.

The only thing to realize is the tricky construction of the objects because they are mutually dependant.

In this case we first create a listbox, then the popup list and then initialize the listbox so the two
controls get linked together.

// Create the listbox
    CAknSingleHeadingPopupMenuStyleListBox* listPane = new ( ELeave ) CAknSingleHeadingPopupMenuStyleListBox;
    CleanupStack::PushL( listPane );

// Create the list pane
    CAknPopupList* popupList = CAknPopupList::NewL(listPane,R_AVKON_SOFTKEYS_OK_EMPTY, AknPopupLayouts::EMenuWindow );
    CleanupStack::PushL( popupList );
    popupList->SetTitleL( _L("Message Details:") );

// Now complete the construction of the listbox - note the view flag settings    `
    listPane->ConstructL( popupList, CEikListBox::ELeftDownInViewRect | CEikListBox::EViewerFlag);
    listPane->CreateScrollBarFrameL( ETrue );
    listPane->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto );

// Finally get the metrics for the columns - all LAF based so no guessing
    const TSize appSize = ApplicationRect().Size();
    listPane->SetSize( appSize );
    const CFormattedCellListBoxItemDrawer* drawer = listPane->ItemDrawer();
    const CFormattedCellListBoxData* data = drawer->ColumnData();
    const TInt width = data->SubCellSize(1).iWidth;
    const CFont* textBoxFont = data->SubCellFont(1);

Now we can create the contents of the listbox as we know how wide the columns are and what font to use
    CDesCArray* array = CreateListBoxRowsL(width, *textBoxFont);

Finally set the listbox contents into the listbox
    CTextListBoxModel* model = listPane->Model();
    model->SetItemTextArray( array );
    model->SetOwnershipType( ELbmOwnsItemArray );
    CleanupStack::Pop(array);


And to finish off display the listbox in the popup list and get a selection
    popupList->ExecuteLD();

Now remember to pop and destroy the various bits
    CleanupStack::Pop(popupList);
    CleanupStack::PopAndDestroy(listPane);
   
   
All that is needed now is the code to build up the rows for the listbox.
So what we do is create an array to hold the data and then fill it based
on the heading and string supplied.
 
LOCAL_C CDesCArray* CreateListBoxRowsL(const TInt aWidth, const CFont& aFont)
    {
    _LIT(KTo, "To:");
    _LIT(KToFields, "dave@email.com, george@email.com");

    _LIT(KSubject, "Subject:");
    _LIT(KSubjectFields, "This is a very long subject to be displayed");

    CDesCArray* itemList = new (ELeave) CDesCArrayFlat(3);
    CleanupStack::PushL(itemList);

    SplitStringL(itemList, KTo, KToFields, aWidth, aFont);
    SplitStringL(itemList, KSubject, KSubjectFields, aWidth, aFont);

    CleanupStack::Pop(itemList);
    return itemList;
    }

There are a number of ways we can split the string, probably the simplist is to use the TextCount, but I decided to use
the WrapToArray for a change.
LOCAL_C void SplitStringL(CDesCArray* aList, const TDesC& aHeading, const TDesC& aString, const TInt aWidth, const CFont& aFont)
    {
    CArrayFix<TPtrC16>* lines = new (ELeave) CArrayFixFlat<TPtrC>(10);
    CleanupStack::PushL(lines);

    TPtr tmp = aString.AllocLC()->Des();
    AknTextUtils::WrapToArrayL(tmp, aWidth, aFont, *lines);

    for (TInt i=0; i < lines->Count(); i++)
        {
        TBuf<255> tmp;

        // If this is the first time we are adding to the array
        // we put the heading in, otherwise we just leave it empty
        // for the first column
        if (i == 0)
            tmp = aHeading;

        // Now add the second column
        tmp.Append(_L("t"));
        TPtrC theLine = lines->At(i);
        tmp.Append(lines->At(i));
        aList->AppendL(tmp);
        }

    CleanupStack::PopAndDestroy(2, lines);
    }

Here is the final result of it all. The elipses ("...") could be got rid of using the font to calculate the width of the text and not the test utils api.


Finished Message Detail Dialog


As usual, email for the complete code

Comments

Re: Creating a message details dialog - the implementation

regan_coleman | 08/01/2007, 07:59

Excellent post as usual Paul. Thanks for sharing!

Re: Creating a message details dialog - the implementation

kstang | 04/02/2007, 18:21

Thanks!
Very useful code!
You must login to post comments. Login
 
 
Powered by LifeType
     
     RDF Facets:
     
     
     qfnZtopicQUqfnTopicZcppQ
     qfnZtopicQUqfnTopicZseriesE5f60Q
     qfnZtypeQUqfnTypeZBlogContentQ
     qfnZtypeQUqfnTypeZBlogE45ntryQ
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX