diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/AknPopupField.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/AknPopupField.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,1317 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +// AknPopupField.cpp +// +// Copyright (c) 1997-2001 Symbian Ltd. All rights reserved. +// + +#include +#include +#include +#include + +#include "AknPopupField.h" +#include "AknQueryValue.h" +#include "aknlists.h" +#include "AknDef.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +_LIT(KPopFieldLeadingLayoutTextActive, "1\t"); +_LIT(KPopFieldLeadingLayoutTextInactive, "\t\t"); +const TInt KDefaultMaxNoLines = 6; + +class CAknPopupFieldExtension : public CBase + { +public: + TRect iFormFieldRect; // moved to extension + TInt iEditTextPos; // position of editable text inside form. 0..5 based on Form data field texts, line 2 baseline from 2.6 spec. + CAknsFrameBackgroundControlContext *iFrameSkinContext; // this will be linked to listbox's context as background. + CAknsBasicBackgroundControlContext *iBgContext; + MTouchFeedback* iFeedback; + TInt iOldItemIndex; + TBool iSingleClickEnabled; + }; + + +//*******************************************************************************************/ +// AknPopupFieldBitmapButton + +CAknPopupField::CAknPopupFieldBitmapButton::CAknPopupFieldBitmapButton() + { + // set all margins to zero, we just want the bitmap with no margin + iMargins.iTop = 0; + iMargins.iBottom = 0; + iMargins.iLeft = 0; + iMargins.iRight = 0; + } + + +//*******************************************************************************************/ +// CAknPopupField + +EXPORT_C CAknPopupField::CAknPopupField() +: iCba( NULL ), + iFormMode( EAknFormModeView ), + iSelectionMode(EAknPopupFieldLabelMode), + iMaxNoLines(KDefaultMaxNoLines) + { + } + +EXPORT_C CAknPopupField::~CAknPopupField() + { + delete iAttemptExitAsync; + delete iLabel; + delete iButton; + DestroyPopout(); + delete iLayoutDecorator; + delete iOtherText; + delete iEmptyText; + delete iInvalidText; + delete iCba; + if (iExtension) + delete iExtension->iBgContext; + if (iExtension) + delete iExtension->iFrameSkinContext; + delete iExtension; + } + +EXPORT_C void CAknPopupField::ConstructL() + { + iEmptyText->Des() = KNullDesC; + iInvalidText->Des() = KNullDesC; + + + CommonConstructL(); + } + +EXPORT_C void CAknPopupField::ConstructFromResourceL(TResourceReader& aReader) + { + iFlags=aReader.ReadInt16(); + iWidth=aReader.ReadInt16(); + iOtherText = aReader.ReadHBufCL(); + iEmptyNoteResourceId = aReader.ReadInt32(); + iEmptyText = aReader.ReadHBufCL(); + iInvalidText = aReader.ReadHBufCL(); + + CommonConstructL(); + } +EXPORT_C void CAknPopupField::SetFormFieldRect(TRect aRect) + { // captioned control will call this + if (iExtension) + iExtension->iFormFieldRect = aRect; + } + + +void CAknPopupField::CommonConstructL() + { + iExtension = new(ELeave)CAknPopupFieldExtension; + iExtension->iSingleClickEnabled = static_cast( + iCoeEnv->AppUi() )->IsSingleClickCompatible(); + + //iExtension = new(ELeave)CAknPopupFieldExtension; + iExtension->iFormFieldRect = TRect(0,0,0,0); + + if (!iOtherText) + iOtherText = HBufC::NewL(0); // set to zero length so we can then test for 0 length later + + iEmptyNoteTimeout = CAknNoteDialog::EShortTimeout; + iEmptyNoteTone = CAknNoteDialog::ENoTone; + + ConstructLabelL(); + if (iFlags & EAknPopupFieldFlagButton) + ConstructCommandButtonL(); + + ConfigureDecorator(); + ConstructLayoutDecoratorL(); + + // layer 1, main_pane background + iExtension->iBgContext = CAknsListBoxBackgroundControlContext::NewL( + KAknsIIDQsnBgAreaMainListGene, TRect(0,0,1,1), ETrue, + KAknsIIDQsnBgColumnAB, TRect(0,0,1,1) ) ; + + //CAknsBasicBackgroundControlContext::NewL( KAknsIIDQsnBgAreaMain, TRect(0,0,1,1), ETrue); + // layer 2, form field highlight + iExtension->iFrameSkinContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrInput, TRect(0,0,1,1), TRect(0,0,1,1), ETrue); + + iExtension->iFeedback = MTouchFeedback::Instance(); + } + +void CAknPopupField::ConstructLabelL() + { + if (iLabel) + return; // already exists + iLabel=new(ELeave) CEikLabel(); + iLabel->SetContainerWindowL(*this); + iLabel->SetTextL(KNullDesC); + } + +void CAknPopupField::ConstructCommandButtonL() + { + } + +void CAknPopupField::ConstructSelectionListL() + { + if (iSelectionList) + return; // already exists + + //TRect rect = Rect(); + if ( iFormMode==EAknFormModeEdit || iFormMode==EAknFormModeView ) + iSelectionList = new(ELeave) CAknFormGraphicStyleListBox; + else if ( iFormMode==EAknFormModeEditWideWithoutGraphic || iFormMode==EAknFormModeViewWideWithoutGraphic ) + iSelectionList = new(ELeave) CAknFormGraphicWideStyleListBox; + else // wide with bitmap for now use wide style + iSelectionList = new(ELeave) CAknFormGraphicWideStyleListBox; + + iSelectionList->ConstructWithWindowL(this, EAknListBoxMultipleSelection); + // We dont want captionedcontrol's skin context, since captionedcontrol has + // different coordinates. (window starts with 0,0). + iSelectionList->SetMopParent(NULL); + iSelectionList->SetParent(this); + + iSelectionList->SetListBoxObserver(this); + + // set the array into the listbox + iSelectionList->Model()->SetItemTextArray(iLayoutDecorator); + iSelectionList->Model()->SetOwnershipType(ELbmDoesNotOwnItemArray); + + iSelectionList->SetObserver(this); + + InitialiseRadioButtonBitmapsL(); + iSelectionList->ItemDrawer()->FormattedCellData()->SetControl(iSelectionList); + //TRect screenRect = AknLayout::screen().Rect(); + iSelectionList->ItemDrawer()->FormattedCellData()->SetBackgroundSkinStyle(&KAknsIIDQsnFrInput, iExtension->iFormFieldRect); + } + + +void CAknPopupField::SetUpScrollBarL() + { + if ( !iExtension || !iExtension->iSingleClickEnabled ) + { + __ASSERT_DEBUG( iCba, Panic( EAknPanicPopupFieldCBADoesntExist ) ); + } + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + iSelectionList->SetMopParent(this); // to get remote scb + iSelectionList->CreateScrollBarFrameL(ETrue, ETrue); + iSelectionList->SetMopParent(NULL); + iSelectionList->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto); + } + +void CAknPopupField::SetScrollBarSelectionL() + { + TInt selection = iValue->CurrentValueIndex(); + if (IsInvalid()) selection = 0; + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + iSelectionList->SetCurrentItemIndex(selection); + iSelectionList->View()->SelectItemL(selection); + + if ( iExtension ) + { + iExtension->iOldItemIndex = iSelectionList->CurrentItemIndex(); + } + } + + +void CAknPopupField::InitialiseRadioButtonBitmapsL() + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_RADIOBUTT_BMP); + + HBufC* bmpFile = reader.ReadHBufCL(); + TInt bmpSelected = reader.ReadInt16(); + TInt bmpSelectedM = reader.ReadInt16(); + TInt bmp = reader.ReadInt16(); + TInt bmpM = reader.ReadInt16(); + CleanupStack::PopAndDestroy(); // reader + + if (bmpFile == NULL) + return; + CleanupStack::PushL(bmpFile); + + if (iFlags & EAknPopupFieldNoGraphic) + {// no graphic + SetShowIndicatorsL(EFalse); + } + + CArrayPtr* icons = iSelectionList->ItemDrawer()->FormattedCellData()->IconArray(); + if ( icons ) + { + icons->ResetAndDestroy(); + } + else + { + icons = new(ELeave) CAknIconArray(2); + iSelectionList->ItemDrawer()->FormattedCellData()->SetIconArrayL(icons); // ownership transferred, cell data deletes all members of list + } + + CFbsBitmap* bitmap = 0; + CFbsBitmap* mask = 0; + + //AknIconUtils::CreateIconLC(bitmap, mask, *bmpFile, bmpSelected, bmpSelectedM); + AknsUtils::CreateColorIconLC( skin, KAknsIIDQgnIndiRadiobuttOn, + KAknsIIDQsnIconColors, + EAknsCIQsnIconColorsCG15, + bitmap, mask, *bmpFile, + bmpSelected, + bmpSelectedM, + KRgbBlack); + + + CGulIcon* gulicon = CGulIcon::NewL(bitmap,mask); // ownership passed + CleanupStack::Pop(); // mask + CleanupStack::Pop(); // bitmap + CleanupStack::PushL(gulicon); + icons->AppendL(gulicon); + CleanupStack::Pop(); // gulicon + + bitmap = 0; + mask = 0; + + //AknIconUtils::CreateIconLC(bitmap, mask, *bmpFile, bmp, bmpM); + AknsUtils::CreateColorIconLC( skin, KAknsIIDQgnIndiRadiobuttOff, + KAknsIIDQsnIconColors, + EAknsCIQsnIconColorsCG15, + bitmap, mask, *bmpFile, + bmp, + bmpM, + KRgbBlack); + + + CGulIcon* gulicon2 = CGulIcon::NewL(bitmap,mask); // ownership passed + CleanupStack::Pop(); // mask + CleanupStack::Pop(); // bitmap + CleanupStack::PushL(gulicon2); + icons->AppendL(gulicon2); + CleanupStack::Pop(); // gulicon2 + + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + + CleanupStack::PopAndDestroy(); // bmpfile + } + +EXPORT_C TSize CAknPopupField::MinimumSize() + { + TSize size(0,0); + TSize minTabSize(0,0); + + switch(iSelectionMode) + { + case EAknPopupFieldLabelMode: + if (iLabel) + size=iLabel->MinimumSize(); + if (iButton) + minTabSize = iButton->MinimumSize(); + size.iWidth+=minTabSize.iWidth+iBorder.Margins().iLeft; + size.iHeight=Max(size.iHeight+iBorder.SizeDelta().iHeight,minTabSize.iHeight); + break; + case EAknPopupFieldSelectionListMode: + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + size = iSelectionList->MinimumSize(); + break; + default: + __ASSERT_DEBUG(ETrue, Panic(EAknPanicPopupFieldUndefinedMode)); + break; + } + return size; + } + + +EXPORT_C void CAknPopupField::SizeChanged() + { + TRAP_IGNORE(DoSizeChangedL()); + } + +EXPORT_C void CAknPopupField::FocusChanged( TDrawNow aDrawNow ) + { + CEikBorderedControl::FocusChanged( aDrawNow ); + if( iSelectionList ) + { + iSelectionList->SetFocus( IsFocused() ); + } + } + +void CAknPopupField::DoSizeChangedL() + { + // captioned control is supposed to set the iFormFieldRect before SizeChanged(). + // note that the iLabel in Label mode is really implemented in wrong place -- popup field should not be + // responsible of the label. + __ASSERT_DEBUG(iExtension && iExtension->iFormFieldRect != TRect(0,0,0,0), Panic(EAknPanicPopupFieldNoFieldRectSet)); + const TRect rect(Rect()); + + switch(iSelectionMode) + { + case EAknPopupFieldLabelMode: + { +#if 0 + TInt mode = (( iFormMode==EAknFormModeEdit + || iFormMode==EAknFormModeEditWideWithGraphic + || iFormMode==EAknFormModeEditWideWithoutGraphic) + && iButton) ? 0 : 1; + TAknTextLineLayout labelLayout(AKN_LAYOUT_TEXT_List_pane_texts__form_graphic__Line_1(0,mode)); + if ( iFormMode==EAknFormModeEdit || iFormMode==EAknFormModeView ) + { + labelLayout = AKN_LAYOUT_TEXT_List_pane_texts__form_graphic__Line_1(0,mode); + } + else if ( iFormMode==EAknFormModeEditWideWithoutGraphic || iFormMode==EAknFormModeViewWideWithoutGraphic ) + { + labelLayout = AKN_LAYOUT_TEXT_List_pane_texts__form_graphic_wide__Line_1(0, mode, 0,0); + } + else // wide with bitmap for now use wide style + { + labelLayout = AKN_LAYOUT_TEXT_List_pane_texts__form_graphic_wide__Line_1(0, mode, 0,0); + } + TAknTextLineLayout labelLayoutFormView(AKN_LAYOUT_TEXT_Form_data_field_texts_Line_2(0)); + +// labelLayout.iFont = labelLayoutFormView.iFont; // for view and edit mode need same font as in form, in expanded mode use from laf + AknLayoutUtils::LayoutLabel(iLabel, rect, labelLayout, AknLayoutUtils::FontFromId(labelLayoutFormView.FontId())); +#endif + TAknTextLineLayout labelLayout(AknLayout::Form_data_field_texts_Line_2(0)); + if (iFormMode == EAknFormModeEdit || iFormMode == EAknFormModeView) + { + labelLayout = AknLayout::Form_data_field_texts_Line_2(0); + } + else if ( iFormMode==EAknFormModeEditWideWithoutGraphic || iFormMode==EAknFormModeViewWideWithoutGraphic ) + { + labelLayout = AknLayout::Form_data_wide_field_texts_Line_2(0); + } + else // wide with bitmap for now use wide style + { + labelLayout = AknLayout::Form_data_wide_graphic_field_texts_Line_2(0); + } + AknLayoutUtils::LayoutLabel(iLabel, iExtension ? iExtension->iFormFieldRect : Rect(), labelLayout); + + if (iButton) + AknLayoutUtils::LayoutControl(iButton, rect, AKN_LAYOUT_WINDOW_List_pane_elements__form_graphic__Line_2); + + if (IsInvalid()) + { + if (iInvalidText) + { + iLabel->SetTextL(*iInvalidText); // takes copy + iLabel->CropText(); + } + else + iLabel->SetTextL(KNullDesC); + } + else if (!IsEmpty()) + { + // update the label if the text should be changed due to the size change + HBufC* newText = iValue->CurrentValueTextLC(); // ownership passed + iLabel->SetTextL(*newText); // takes copy + CleanupStack::PopAndDestroy(); // newText + iLabel->CropText(); + } + else + { + if (iEmptyText) + { + iLabel->SetTextL(*iEmptyText); // takes copy + iLabel->CropText(); + } + else + iLabel->SetTextL(KNullDesC); + } + + // reset the border to none + if (iButton) + iButton->SetBorder(TGulBorder::ENone); + break; + } + case EAknPopupFieldSelectionListMode: + { + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + iSelectionList->SetRect(rect); + AknsUtils::RegisterControlPosition(this); + AknsUtils::RegisterControlPosition(iSelectionList); + TRect listBoxRect = iExtension->iFormFieldRect; //iSelectionList->Rect(); + listBoxRect.iTl = TPoint(0,0); + // Cannot use KAknsIIDNone here because highlight animation + // creation would fail in eikfrlbd.cpp (with KAknsIIDNone there + // would be no background to animate). + iSelectionList->ItemDrawer()->FormattedCellData()->SetBackgroundSkinStyle(&KAknsIIDNone, listBoxRect); + //iSelectionList->ItemDrawer()->FormattedCellData()->SetBackgroundSkinStyle(&KAknsIIDNone /*Center*/, /*Rect()*/ /*TRect(0,0,176,208)*/); + TAknLayoutRect frame_tl; + frame_tl.LayoutRect(listBoxRect, SkinLayout::Input_field_skin_placing__general__Line_2()); + TAknLayoutRect frame_br; + frame_br.LayoutRect(listBoxRect, SkinLayout::Input_field_skin_placing__general__Line_5()); + TRect center = TRect(frame_tl.Rect().iBr, frame_br.Rect().iTl); + + // + // Skin contexts are in 3 layers: + // 1) background + // 2) form field highlight + // 3) list context + if (iExtension) + { + TRect main_pane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, main_pane ); + + TRect clientRect = main_pane; + TPoint ctrlPoint = PositionRelativeToScreen(); + + TPoint innerPoint = Rect().iTl; + clientRect.iTl.iX -= ctrlPoint.iX; + clientRect.iBr.iX -= ctrlPoint.iX; + clientRect.iTl.iY -= ctrlPoint.iY; + clientRect.iBr.iY -= ctrlPoint.iY; + + clientRect.iTl.iX += innerPoint.iX; + clientRect.iBr.iX += innerPoint.iX; + clientRect.iTl.iY += innerPoint.iY; + clientRect.iBr.iY += innerPoint.iY; + + + //TPoint p = clientRect.iTl; + iExtension->iBgContext -> SetParentPos(main_pane.iTl); + iExtension->iBgContext -> SetRect(clientRect /*TRect(c,clientRect.Size())*/); + } + + if (iExtension) + { + // Calculate formfieldRect relative to screen. + TPoint p; + p = PositionRelativeToScreen(); + p.iX += iExtension->iFormFieldRect.iTl.iX; + p.iY += iExtension->iFormFieldRect.iTl.iY; + p.iX -= Rect().iTl.iX; + p.iY -= Rect().iTl.iY; + iExtension->iFrameSkinContext -> SetParentPos( p /*iSelectionList->PositionRelativeToScreen()*/ ); + + + iExtension->iFrameSkinContext -> SetFrameRects(listBoxRect, center); + iExtension->iFrameSkinContext -> SetFrame(KAknsIIDQsnFrInput ); // frInput or frList? + iExtension->iFrameSkinContext -> SetParentContext(iExtension->iBgContext); + } + CAknsBasicBackgroundControlContext *bgContext = (CAknsBasicBackgroundControlContext*)iSelectionList->ItemDrawer()->FormattedCellData()->SkinBackgroundContext(); + if (iExtension) + { + bgContext->SetParentContext(iExtension->iFrameSkinContext); + //iExtension->iFrameSkinContext -> SetParentPos( iSelectionList->PositionRelativeToScreen() ); + + } + TRect main_pane = iAvkonAppUi->ClientRect(); + + TAknLayoutRect listscroll_form_pane_rect; + listscroll_form_pane_rect.LayoutRect(main_pane, AknLayoutScalable_Avkon::listscroll_form_pane()); + + + // set SVG icons (call SizeChanged between InitialiseRadioButtonBitmapsL and Draw) + CArrayPtr *iconarray = 0; + iconarray = iSelectionList->ItemDrawer()->FormattedCellData()->IconArray(); + + if (iconarray) + { + TInt iconCount = iconarray->Count(); + if (iconCount) + { + TAknLayoutRect rect; + rect.LayoutRect(Rect(), AKN_LAYOUT_WINDOW_List_pane_elements__form_graphic__Line_2); + for (TInt i = 0 ; i < iconCount ; i++) + AknIconUtils::SetSize((*iconarray)[i]->Bitmap(), rect.Rect().Size()); + } + } + break; + } + default: + __ASSERT_DEBUG(ETrue, Panic(EAknPanicPopupFieldUndefinedMode)); + break; + } + iFlags |= EAknPopupFieldFlagInitialised; + } + + +EXPORT_C TKeyResponse CAknPopupField::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) + { + switch(iSelectionMode) + { + case EAknPopupFieldLabelMode: + { + TBool okPressed = aKeyEvent.iCode==EKeyTab || aKeyEvent.iCode == EKeyEnter || aKeyEvent.iCode == EKeyOK; + switch(aKeyEvent.iCode) + { + case EKeyTab: // fall through + case EKeyEnter: // fall through + case EKeyOK: + if ((okPressed) && (!(aKeyEvent.iModifiers&EModifierCtrl) || aKeyEvent.iModifiers&EModifierPureKeycode)) + { + // note also that when page goes from view to edit mode, controls go from nonfocusing to focusing + // therefore we only want focusing controls that have the focus + if (!IsNonFocusing() && IsFocused()) + { + if (!IsEmpty()) + { + CreatePopoutL(); + // In single click, enable highlight when opening + // with hw key + if ( iExtension + && iExtension->iSingleClickEnabled + && iSelectionList ) + { + TKeyEvent enterEvent( aKeyEvent ); + enterEvent.iCode = EKeyEnter; + iSelectionList->OfferKeyEventL( + enterEvent, aType ); + } + } + else + ShowEmptyListNoteL(); + return EKeyWasConsumed; + } + else + return EKeyWasNotConsumed; + } + break; + case EKeyLeftArrow: // fall through + case EKeyRightArrow: + return HandleHorizontalKeyEventL(aKeyEvent.iCode); + default: + return EKeyWasNotConsumed; + } + } + break; + case EAknPopupFieldSelectionListMode: + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + return iSelectionList->OfferKeyEventL(aKeyEvent,aType); + default: + __ASSERT_DEBUG(ETrue, Panic(EAknPanicPopupFieldUndefinedMode)); + break; + } + return EKeyWasConsumed; + } + +EXPORT_C void CAknPopupField::HandleControlEventL(CCoeControl* aControl,TCoeEvent aEvent) + { + switch (aEvent) + { + case EEventRequestFocus: // drop through + case EEventPrepareFocusTransition: + ReportEventL(aEvent); + break; + case EEventStateChanged: + if (aControl != NULL && aControl==iButton) + CreatePopoutL(); + break; + case EEventRequestExit: + break; + case EEventRequestCancel: + if ( AknLayoutUtils::PenEnabled() ) + { + AttemptExitL(EFalse); + } + break; + default: + break; + } + } + +EXPORT_C void CAknPopupField::ProcessCommandL(TInt aCommandId) + { + // Respond to softkey events + switch (aCommandId) + { + case EAknSoftkeyOk: + AttemptExitL(ETrue); + break; + case EAknSoftkeyCancel: + AttemptExitL(EFalse); + break; + default: + break; + } + } + +EXPORT_C void CAknPopupField::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType) + { + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + if (aListBox == iSelectionList) + { + switch ( aEventType ) + { + case MEikListBoxObserver::EEventItemSingleClicked: + { + CListBoxView* view = iSelectionList->View(); + + if ( view->CurrentItemIndex() != iExtension->iOldItemIndex ) + { + view->DeselectItem( iExtension->iOldItemIndex ); + iExtension->iOldItemIndex = view->CurrentItemIndex(); + view->SelectItemL( iExtension->iOldItemIndex ); + } + } + + case MEikListBoxObserver::EEventItemDoubleClicked: + case MEikListBoxObserver::EEventEnterKeyPressed: + { + // We can't delete the selection list until it's finished + // processing the event, so call ourselves back and do it when + // the list has finished. + TCallBack cb( AttemptExitCallbackL, this ); + delete iAttemptExitAsync; + iAttemptExitAsync = NULL; + iAttemptExitAsync = new ( ELeave ) + CAsyncCallBack( cb, CActive::EPriorityHigh ); + iAttemptExitAsync->CallBack(); + } + break; + + default: + break; + } + } + } + + +EXPORT_C TInt CAknPopupField::CountComponentControls() const + { + CCoeControl* controls[] = + { + iButton, + iLabel, + iSelectionList + }; + + TInt count = 0; + for (TUint ii=0; iiSetTextL(KNullDesC); + } + else if (IsInvalid()) + { + if (iInvalidText) + { + iLabel->SetTextL(*iInvalidText); + iLabel->CropText(); + } + else iLabel->SetTextL(KNullDesC); + ReportEventL(EEventStateChanged); + if (iObserver) + iObserver->HandlePopupFieldEventL(this, MAknPopupFieldObserver::EAknPopupFieldEventValueChange, 0); + } + else + { + HBufC* newText = iValue->CurrentValueTextLC(); // ownership passed + iLabel->SetTextL(*newText); // takes copy + CleanupStack::PopAndDestroy(); // newText + iLabel->CropText(); + ReportEventL(EEventStateChanged); + if (iObserver) + iObserver->HandlePopupFieldEventL(this, MAknPopupFieldObserver::EAknPopupFieldEventValueChange, 0); + } + return ETrue; + } + +void CAknPopupField::DestroyPopout() + { + if (iSelectionList) + { + iEikonEnv->RemoveFromStack(iSelectionList); + delete iSelectionList; + iSelectionList=NULL; + } + } + +TBool CAknPopupField::IsEmpty() const + { + if (!iValue) + return ETrue; + if (iDecorator.MdcaCount() <= 0) + return ETrue; + return EFalse; + } + +TBool CAknPopupField::IsInvalid() const + { + if (IsEmpty()) return EFalse; + TInt valueIndex = iValue->CurrentValueIndex(); + if (valueIndex < 0 || valueIndex >= iDecorator.MdcaCount()) + return ETrue; + return EFalse; + } + +TKeyResponse CAknPopupField::HandleHorizontalKeyEventL(TUint aKeyEventCode) + { + TKeyResponse keyResponse = EKeyWasNotConsumed; + TBool finished = EFalse; + + TInt decIndex = 0; + if (IsEmpty() || (iDecorator.MdcaCount() == 1 && iDecorator.DecoratedIndex(decIndex))) + finished = ETrue; // Popupfield was empty or just contained decorated item + + TInt changeIndexBy = 0; + if (!finished) + { + TBool isMirrored = AknLayoutUtils::LayoutMirrored(); + + switch(aKeyEventCode) + { + case EKeyLeftArrow: + changeIndexBy = (isMirrored ? 1 : -1); + break; + case EKeyRightArrow: + changeIndexBy = (isMirrored ? -1 : 1); + break; + default: + finished = ETrue; // Not a horizontal key event + break; + } + } + + if (!finished) + { + TInt newValue = iValue->CurrentValueIndex() + changeIndexBy; + if (newValue < 0) // cycle around + { + newValue = iValue->MdcArray()->MdcaCount() - 1; + } + else if (newValue > (iValue->MdcArray()->MdcaCount() - 1)) // cycle around + { + newValue = 0; + } + if (newValue != iValue->CurrentValueIndex()) + { + iValue->SetCurrentValueIndex(newValue); + HandleInteractionConfirmedL(); + DrawDeferred(); + } + keyResponse = EKeyWasConsumed; + } + + return keyResponse; + } + +void CAknPopupField::CreatePopoutL() + { + if ( !iExtension || !iExtension->iSingleClickEnabled ) + { + CreateCbaL(); + } + ConstructSelectionListL(); + ChangeMode(EAknPopupFieldSelectionListMode); + SetUpScrollBarL(); + // need to initialize the selection so that the list box is drawn in the correct place + SetScrollBarSelectionL(); + // make the selection list visible and update the scrollbar + SetScrollBarSelectionL(); + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + iSelectionList->MakeVisible(ETrue); + iSelectionList->ActivateL(); + iSelectionList->SetFocus(ETrue); + iSelectionList->UpdateScrollBarsL(); + + // now let the container resize the list box + if (iObserver) + iObserver->HandlePopupFieldEventL(this, MAknPopupFieldObserver::EAknPopupFieldEventModeChange, NumLines()); + } + + +void CAknPopupField::CreateCbaL() + { + CEikButtonGroupContainer* cba = CEikButtonGroupContainer::NewL( + CEikButtonGroupContainer::ECba, + CEikButtonGroupContainer::EHorizontal, + this, // popup field is a command observer + R_AVKON_SOFTKEYS_OK_CANCEL__OK); + + delete iCba; + iCba = cba; + + const TSize screenSize=iAvkonAppUi->ApplicationRect().Size(); /*TSize(AKN_LAYOUT_WINDOW_screen.iW, AKN_LAYOUT_WINDOW_screen.iH);*/ + iCba->SetBoundingRect(TRect(screenSize)); + } + + +EXPORT_C void CAknPopupField::HandleResourceChange(TInt aType) + { + EAknFormMode newMode( iFormMode ); + TBool notEditable( EFalse ); + switch( aType ) + { + case KEikMessageCaptionedControlEditableStateChange: + { + newMode = EAknFormModeEdit; + break; + } + case KEikMessageCaptionedControlEditableStateChangeWideWithGraphic: + { + newMode = EAknFormModeEditWideWithGraphic; + break; + } + case KEikMessageCaptionedControlEditableStateChangeWideWithoutGraphic: + { + newMode = EAknFormModeEditWideWithoutGraphic; + break; + } + case KEikMessageCaptionedControlNotEditableStateChange: + { + newMode = EAknFormModeView; + notEditable = ETrue; + break; + } + case KEikMessageCaptionedControlNotEditableStateChangeWideWithGraphic: + { + newMode = EAknFormModeViewWideWithGraphic; + notEditable = ETrue; + break; + } + case KEikMessageCaptionedControlNotEditableStateChangeWideWithoutGraphic: + { + newMode = EAknFormModeViewWideWithoutGraphic; + notEditable = ETrue; + break; + } + default: + { + break; + } + } + if ( newMode != iFormMode ) + { + if ( iSelectionList && notEditable + && iSelectionMode == EAknPopupFieldSelectionListMode + && iExtension && iExtension->iSingleClickEnabled ) + { + // Edit mode to view while popup is open -> first cancel popup + AttemptExitL( EFalse ); + } + else + { + __ASSERT_DEBUG( iSelectionMode == EAknPopupFieldLabelMode, + Panic( EAknPanicPopupFieldWrongMode ) ); + } + iFormMode = newMode; + if ( iButton && + ( notEditable || ( iValue && iDecorator.MdcaCount() != 0 ) ) ) + { + iButton->MakeVisible( !notEditable ); + } + } + if ( iSelectionList && !IsEmpty() ) + { + TRAP_IGNORE( InitialiseRadioButtonBitmapsL() ); + } + + CEikBorderedControl::HandleResourceChange(aType); + } + +//--------------------------------------------------------------------------------------- +// CAknPopupField::HandlePointerEventL() +// Starts popuplist or empty popuplist when popup item is clicked +//--------------------------------------------------------------------------------------- +// +EXPORT_C void CAknPopupField::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + if ( AknLayoutUtils::PenEnabled() ) + { + if ( aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + // note also that when page goes from view to edit mode, controls go from nonfocusing to focusing + // therefore we only want focusing controls that have the focus + if (!IsNonFocusing() && IsFocused()) + { + if ( iExtension && iExtension->iFeedback ) + { + iExtension->iFeedback->InstantFeedback( + this, + ETouchFeedbackPopUp, + ETouchFeedbackVibra, + aPointerEvent ); + } + if (!IsEmpty()) + { + CreatePopoutL(); + } + else + { + ShowEmptyListNoteL(); + } + } + } + else if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + if (!IsNonFocusing() + && IsFocused() + && iExtension->iFormFieldRect.Contains( aPointerEvent.iPosition )) + { + // clicked inside popup field, will open popup or note + if ( iExtension && iExtension->iFeedback ) + { + iExtension->iFeedback->InstantFeedback( ETouchFeedbackPopUp ); + } + } + if ( iSelectionList && iSelectionMode == EAknPopupFieldSelectionListMode ) + { + // Clicked outside popup form field, closing popup + if ( !iExtension->iFormFieldRect.Contains( aPointerEvent.iParentPosition ) ) + { + if ( iExtension && iExtension->iFeedback ) + { + iExtension->iFeedback->InstantFeedback( ETouchFeedbackPopUp ); + } + AttemptExitL( EFalse ); + } + } + } + } + } + + +EXPORT_C void* CAknPopupField::ExtensionInterface( TUid /*aInterface*/ ) + { + return NULL; + } + + +EXPORT_C void CAknPopupField::Reserved_1() + {} +EXPORT_C void CAknPopupField::Reserved_2() + {} + + + +EXPORT_C void CAknPopupField::SetAllowsUserDefinedEntry(TBool aAllows) + { + if (aAllows) + { + if (iOtherText->Length() > 0) + iFlags |= EAknPopupFieldFlagAllowsUserDefinedEntry; + } + else + iFlags &= ~EAknPopupFieldFlagAllowsUserDefinedEntry; + + ConfigureDecorator(); + } + + +EXPORT_C void CAknPopupField::ActivateSelectionListL() + { + if (!IsEmpty()) + { + CreatePopoutL(); + } + else + { + ShowEmptyListNoteL(); + } + } + +EXPORT_C void CAknPopupField::SetQueryValueL(MAknQueryValue* aValue) + { + __ASSERT_DEBUG(aValue, Panic(EAknPanicPopupFieldInvalidValue)); + + iValue = aValue; + + if (iFlags & EAknPopupFieldFlagInitialised) + { + // put the current value text into the label + HBufC* newText = iValue->CurrentValueTextLC(); + iLabel->SetTextL(*newText); // takes copy + CleanupStack::PopAndDestroy(); // newText + iLabel->CropText(); + if (iObserver) + { + iObserver->HandlePopupFieldEventL( this, + MAknPopupFieldObserver::EAknPopupFieldEventValueChange, 0 ); + } + } + + // decorate the array from the query value + const MDesCArray* array = iValue->MdcArray(); + iDecorator.SetArray(array); + } + +EXPORT_C void CAknPopupField::SetFont(const CFont* aFont) + { + if (iLabel) + iLabel->SetFont(aFont); + } + +EXPORT_C void CAknPopupField::SetShowIndicatorsL(TBool aShowIndicators) + { + if (!aShowIndicators) + { + if (iLayoutDecorator) + iLayoutDecorator->SetLeadingDecorationTextL(KPopFieldLeadingLayoutTextInactive); + } + } + +EXPORT_C TInt CAknPopupField::NumLines() const + { + TInt lines = 0; + + switch(iSelectionMode) + { + case EAknPopupFieldLabelMode: + lines = 1; + break; + case EAknPopupFieldSelectionListMode: + lines = iDecorator.MdcaCount(); + break; + default: + __ASSERT_DEBUG(ETrue, Panic(EAknPanicPopupFieldUndefinedMode)); + break; + } + + // we must restrict ourselves to the max number of lines. + if (lines > iMaxNoLines) + lines = iMaxNoLines; + return lines; + } + +EXPORT_C void CAknPopupField::SetPopupFieldObserver(MAknPopupFieldObserver* aObserver) + { + iObserver = aObserver; + } + +EXPORT_C void CAknPopupField::SetEmptyListNoteL(TInt aResourceId, CAknNoteDialog::TTimeout aTimeout, CAknNoteDialog::TTone aTone) + { + iEmptyNoteResourceId = aResourceId; + iEmptyNoteTimeout = aTimeout; + iEmptyNoteTone = aTone; + } + +EXPORT_C void CAknPopupField::SetEmptyTextL(const TDesC& aEmptyText) + { + HBufC* newText = aEmptyText.AllocLC(); + delete iEmptyText; + iEmptyText = NULL; + iEmptyText = newText; + CleanupStack::Pop(); // newText + + if (IsEmpty()) + { + iLabel->SetTextL(*iEmptyText); + iLabel->CropText(); + DrawDeferred(); + } + } + +EXPORT_C void CAknPopupField::SetOtherTextL(const TDesC& aOtherText) + { + if (aOtherText.Length() < 1) + return; + + HBufC* newText = aOtherText.AllocLC(); + delete iOtherText; + iOtherText = NULL; + iOtherText = newText; + CleanupStack::Pop(); // newText + + ConfigureDecorator(); + } + +EXPORT_C void CAknPopupField::SetInvalidTextL(const TDesC& aInvalidText) + { + HBufC* newText = aInvalidText.AllocLC(); + delete iInvalidText; + iInvalidText = NULL; + iInvalidText = newText; + CleanupStack::Pop(); // newText + + if (IsInvalid()) + { + iLabel->SetTextL(*iInvalidText); + iLabel->CropText(); + } + } + + +void CAknPopupField::ConfigureDecorator() + { + __ASSERT_DEBUG(iOtherText, Panic(EAknPanicPopupFieldUninitialisedMember)); + + iDecorator.SetDecorationText(*iOtherText); + iDecorator.SetActive(iFlags & EAknPopupFieldFlagAllowsUserDefinedEntry); + } + +void CAknPopupField::ConstructLayoutDecoratorL() + { + if (iLayoutDecorator) + return; // already exists + iLayoutDecorator = CAknListBoxLayoutDecorator::NewL(); + TPtrC textPtr(KPopFieldLeadingLayoutTextActive); + iLayoutDecorator->SetLeadingDecorationTextL(textPtr); + iLayoutDecorator->SetArray(&iDecorator); + iLayoutDecorator->SetActive(ETrue); // for now + } + +void CAknPopupField::ShowEmptyListNoteL() + { + if (!iEmptyNoteResourceId) + return; + CAknNoteDialog* dlg = new (ELeave) CAknNoteDialog(iEmptyNoteTone,iEmptyNoteTimeout); + dlg->PrepareLC(iEmptyNoteResourceId); + dlg->RunLD(); + } + +void CAknPopupField::AttemptExitL(TBool aAccept) + { + // we must be in selection list mode in order to get the cba event + __ASSERT_DEBUG(iSelectionMode == EAknPopupFieldSelectionListMode, Panic(EAknPanicPopupFieldWrongMode)); + __ASSERT_DEBUG(iSelectionList != NULL, Panic(EAknPanicPopupFieldSelectionListDoesntExist)); + TBool finished = ETrue; + + if (aAccept) + { + // get current selection + const TInt selection=iSelectionList->CurrentItemIndex(); + TInt decoratedIndex; + TBool decorated = iDecorator.DecoratedIndex(decoratedIndex); + if (decorated && (selection == decoratedIndex)) + { + TBool accepted = iValue->CreateEditorL(); + if (!accepted) + { + // dialog was cancelled, so popup list must remain + finished = EFalse; + } + } + else + iValue->SetCurrentValueIndex(selection); + } + + if (finished) + { + delete iCba; + iCba = NULL; + DestroyPopout(); + ChangeMode(EAknPopupFieldLabelMode); + // Move up to make sure the following line is always executed + if (iObserver) + iObserver->HandlePopupFieldEventL(this, MAknPopupFieldObserver::EAknPopupFieldEventModeChange, NumLines()); + + if (aAccept) + HandleInteractionConfirmedL(); + + } + } + +void CAknPopupField::ChangeMode(EAknPopupFieldSelectionMode aNewMode) + { + // change mode, and show / hide the appropriate controls + switch(aNewMode) + { + case EAknPopupFieldLabelMode: + iSelectionMode = EAknPopupFieldLabelMode; + iLabel->MakeVisible(ETrue); + if (iButton) + iButton->MakeVisible(ETrue); + break; + case EAknPopupFieldSelectionListMode: + iSelectionMode = EAknPopupFieldSelectionListMode; + iLabel->MakeVisible(EFalse); + if (iButton) + iButton->MakeVisible(EFalse); + break; + default: + __ASSERT_DEBUG(ETrue, Panic(EAknPanicPopupFieldUndefinedMode)); + break; + } + } + +TInt CAknPopupField::AttemptExitCallbackL(TAny* aThis) + { + if (aThis) + { + static_cast(aThis)->DoAttemptExitL(); + } + return 0; + } + +void CAknPopupField::DoAttemptExitL() + { + AttemptExitL(ETrue); + delete iAttemptExitAsync; + iAttemptExitAsync = NULL; + } + +EXPORT_C void CAknPopupField::SetMaxNumberOfLinesPermitted(TInt aMaxNoLines) + { + iMaxNoLines = aMaxNoLines; + }; + +EXPORT_C TTypeUid::Ptr CAknPopupField::MopSupplyObject(TTypeUid aId) + { + // Only thing supplied at this level of descent in the class hierarchy + // or in the object provider chain is the cba + if ( iCba ) + { + TTypeUid::Ptr myPtr( SupplyMopObject( aId, iCba ) ); + if ( myPtr.Pointer() ) + { + return myPtr; + } + } + return CEikBorderedControl::MopSupplyObject( aId ); + } + +EXPORT_C void CAknPopupField::Draw(const TRect& aRect) const + { + if ( iSelectionMode == EAknPopupFieldSelectionListMode ) + { + TBool backgroundDrawn = EFalse; + + if ( AknsUtils::AvkonSkinEnabled() ) + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* edCc = AknsDrawUtils::ControlContext( this ); + CWindowGc& gc = SystemGc(); + backgroundDrawn = AknsDrawUtils::Background( skin, edCc, this, gc, aRect ); + iLabel->SetBrushStyle(CGraphicsContext::ENullBrush); + } + + if ( !backgroundDrawn ) + { + // This should be the legacy behaviour (there was no draw routine before 2.0) + CEikBorderedControl::Draw( aRect ); + iLabel->SetBrushStyleFromContext(); + } + } + } + +// End of File