×
Namespaces

Variants
Actions

How to create a flexible input dialog

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata
Code ExampleArticle
Created: dougcn (07 Aug 2010)
Last edited: hamishwillee (26 Jul 2012)

How to create a flexible input dialog?

Contents

What it is?

It is an input dialog which has as many input items as you want at runtime. Each input item has these properties: prompt, value, name, type and maxlength. And the items can be created at runtime also. In fact, It's just like INPUT elements in a HTTP FORM. Currently, the flexible item can support three types: text, hidden, password. A invisible item is not displayed in dialog. You can extend it yourself to support more types, such as number, date, time, etc.

Now let's get started.

The flexible item definition: CFlexItem

First, we need define a flexible item class which has properties: prompt, type, value, maxlength, etc. See below:

The implementation of CFlexItem,

CFlexItem::CFlexItem() : iMaxLength(KFlexItemMaxLength)
{
// No implementation required
}
 
CFlexItem::~CFlexItem()
{
delete iName;
delete iPrompt;
delete iValue;
delete iType;
}
 
CFlexItem* CFlexItem::NewLC(const TDesC& aPrompt, const TDesC& aName, const TDesC& aType, const TDesC& aValue)
{
CFlexItem* self = new (ELeave) CFlexItem();
CleanupStack::PushL(self);
self->ConstructL(aPrompt, aName, aType, aValue);
return self;
}
 
CFlexItem* CFlexItem::NewL(const TDesC& aPrompt, const TDesC& aName, const TDesC& aType, const TDesC& aValue)
{
CFlexItem* self = CFlexItem::NewLC(aPrompt, aName, aType, aValue);
CleanupStack::Pop(); // self;
return self;
}
 
void CFlexItem::ConstructL(const TDesC& aPrompt, const TDesC& aName, const TDesC& aType, const TDesC& aValue)
{
iName = aName.AllocL();
iPrompt = aPrompt.AllocL();
iType = aType.AllocL();
iValue = aValue.AllocL();
}
 
void CFlexItem::SetValueL(const TDesC& aValue)
{
HBufC* value = aValue.AllocL();
delete iValue; iValue = value;
}
 
void CFlexItem::SetTypeL(const TDesC& aType)
{
HBufC* type = aType.AllocL();
delete iType; iType = type;
}
 
void CFlexItem::SetMaxLengthL(const TDesC& aMaxLength)
{
TLex lex(aMaxLength);
User::LeaveIfError(lex.Val(iMaxLength));
if (iMaxLength > KFlexItemMaxLength)
iMaxLength = KFlexItemMaxLength;
}

The declaration of CFlexItem,

_LIT(KFlexItemTypeHidden, "hidden");   // invisible item
_LIT(KFlexItemTypeText, "text"); // normal item
_LIT(KFlexItemTypePassword, "password"); // Its MD5 value required when HTTP POST
 
/**
* CFlexItem
*
*/

class CFlexItem : public CBase
{
public:
// Constructors and destructor
~CFlexItem();
static CFlexItem* NewL(const TDesC& aPrompt, const TDesC& aName, const TDesC& aType, const TDesC& aValue);
static CFlexItem* NewLC(const TDesC& aPrompt, const TDesC& aName, const TDesC& aType, const TDesC& aValue);
 
public:
inline TPtrC Name() const;
inline TPtrC Prompt() const;
inline TPtrC Value() const;
inline TPtrC Type() const;
inline TInt MaxLength() const;
 
void SetValueL(const TDesC& aValue);
void SetTypeL(const TDesC& aType);
void SetMaxLengthL(const TDesC& aMaxLength);
 
private:
CFlexItem();
void ConstructL(const TDesC& aPrompt, const TDesC& aName, const TDesC& aType, const TDesC& aValue);
 
private:
HBufC* iName; // form post item
HBufC* iPrompt; // dialog input caption
HBufC* iValue; // user input
HBufC* iType; // item type: text, password, hidden,
TInt iMaxLength;
};
 
inline TPtrC CFlexItem::Name() const
{ return *iName; }
inline TPtrC CFlexItem::Prompt() const
{ return *iPrompt; }
inline TPtrC CFlexItem::Value() const
{ return *iValue; }
inline TPtrC CFlexItem::Type() const
{ return *iType; }
inline TInt CFlexItem::MaxLength() const
{ return iMaxLength; }
 
typedef RPointerArray<CFlexItem> RFlexItemArray;

The flexible input dialog definition: CFlexInputDialog

Now we need a dialog to display these dynamic items.

Load data from flexible item array.

void CFlexInputDialog::LoadFormDataL()
{
iConsumed = 0;
iItemValues.ResetAndDestroy();
for (TInt i=iBaseVisibleItemIndex; i<iVisibleItems.Count(); ++i)
{
if (iConsumed >= KMaxDlgItemCount) break;
 
TInt controlId = EFlexItemBase + iConsumed;
SetControlCaptionL(controlId, iItems[iVisibleItems[i]]->Prompt());
 
HBufC* value = HBufC::NewLC(KFlexItemMaxLength);
value->Des().Copy(iItems[iVisibleItems[i]]->Value());
iItemValues.AppendL(value);
CleanupStack::Pop(value);
 
CEikEdwin* item = (CEikEdwin*)Control(controlId);
TInt maxlength = iItems[iVisibleItems[i]]->MaxLength();
item->SetMaxLength(maxlength);
item->SetTextL(value);
 
iConsumed++;
}
for (TInt i(iConsumed); i<KMaxDlgItemCount; ++i)
{
TInt controlId = EFlexItemBase + i;
// SetLineDimmedNow(controlId, ETrue);
this->DeleteLine(controlId);
}
}

And call the above function in

void CFlexInputDialog::PreLayoutDynInitL()
{
CAknForm::PreLayoutDynInitL();
LoadFormDataL();
}

After the end user input texts, and press OK button, we use SaveFormDataL() to collect and check the data. If all is ok, return ETrue otherwise EFalse.

TBool CFlexInputDialog::SaveFormDataL()
{
TBool ok(ETrue);
iConsumed = 0;
for (TInt i=iBaseVisibleItemIndex; i<iVisibleItems.Count(); ++i)
{
if (iConsumed >= KMaxDlgItemCount) break;
 
TInt controlId = EFlexItemBase + iConsumed;
CEikEdwin* item = (CEikEdwin*)Control(controlId);
TPtr ptr(iItemValues[iConsumed]->Des());
item->GetText(ptr);
ptr.TrimAll();
if (ptr.Length() == 0)
{
ok = EFalse;
TryChangeFocusToL(controlId);
break;
}
iItems[iVisibleItems[i]]->SetValueL(ptr);
iConsumed++;
}
 
return ok;
}

and call SaveFormData in OkToExitL() function:

TBool CFlexInputDialog::OkToExitL( TInt aButtonId )
{
TBool ok(EFalse);
if (aButtonId == -2) // EEikBidOK
{
ok = SaveFormDataL();
}
return ok;
}

Our input dialog uses the following dialog resource which defines 10 text input items,

RESOURCE DIALOG r_dialog_flex_query10
{
flags = EEikDialogFlagNoDrag | EEikDialogFlagFillAppClientRect |
EEikDialogFlagCbaButtons | EEikDialogFlagWait;
buttons = R_AVKON_SOFTKEYS_OK_CANCEL;
form = r_dialog_flex_form10;
}
 
RESOURCE FORM r_dialog_flex_form10
{
flags = EEikFormUseDoubleSpacedFormat | EEikFormEditModeOnly;
items =
{
DLG_LINE
{
type = EEikCtEdwin;
prompt = "";
id = EFlexItem0001;
itemflags = EEikDlgItemTakesEnterKey | EEikDlgItemOfferAllHotKeys;
control = EDWIN
{
flags = EEikEdwinNoHorizScrolling | EEikEdwinResizable/* | EEikEdwinWidthInPixels*/;
width = FLEXINPUTDIALOG_EDWIN_WIDTH;
lines = FLEXINPUTDIALOG_EDWIN_LINES;
maxlength = KFlexItemMaxLength;
max_view_height_in_lines = 5;
base_line_delta = 21;
};
},
// up to 10 items, omitted.

The dialog lines can be created at runtime also, you can change it yourself.

Show more input items

If there are more than 10 items, the next 10 will be displayed in next page, and so forth.

TInt DlgUtil::ShowFlexInputDialogL(RFlexItemArray& aItems)
{
TInt ret(KErrNotSupported);
 
RArray<TInt> items;
CleanupClosePushL(items);
for (TInt i(0); i<aItems.Count(); ++i)
{
if (aItems[i]->Type().Compare(KFlexItemTypeHidden) != 0)
items.Append(i);
}
TInt index(0);
while (index < items.Count())
{
TInt consumed = 0;
CAknForm* dlg = new ( ELeave ) CFlexInputDialog( aItems, items, index, consumed );
CleanupStack::PushL( dlg );
dlg->ConstructL( 0 );
CleanupStack::Pop( dlg );
ret = dlg->ExecuteLD(R_DIALOG_FLEX_QUERY10);
index += consumed;
 
if (!ret)
break;
}
 
CleanupStack::PopAndDestroy(&items);
 
return ret;
}

How to use it

Example:

	// define flex item array variable
RFlexItemArray items;
CleanupClosePushL(items);
 
// create sample data
TBuf<100> prompt, value, name, type;
 
for (TInt i(0); i < 32; ++i)
{
prompt.Copy(_L("Caption "));
prompt.AppendNum(i);
 
value.Copy(_L("default value"));
value.AppendNum(i * 2);
 
name.Copy(_L("Name"));
name.AppendNum(i);
 
// create normal text input, or hidden item
type.Copy((i % 5 != 0) ? _L("text") : _L("hidden"));
 
CFlexItem* item = CFlexItem::NewLC(prompt, name, type, value);
items.AppendL(item);
CleanupStack::Pop(item);
}
 
// Show flexible dialog
TInt ret = DlgUtil::ShowFlexInputDialogL(items);
 
// check return value
if (ret)
{
// Ok pressed, so use items here.
CAknInformationNote* informationNote = new (ELeave) CAknInformationNote;
informationNote->ExecuteLD(_L("Ok"));
}
else
{
// Cancel pressed.
}
 
// clean
items.ResetAndDestroy();
CleanupStack::PopAndDestroy(&items);

A demo application

Download a demo app here: FlexDialogDemo.zip.

This page was last modified on 26 July 2012, at 03:02.
37 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×