--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/eikctl/src/EIKMFNE.CPP Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,4614 @@
+/*
+* Copyright (c) 1997-1999 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:
+*
+*/
+
+
+#include <basched.h>
+#include <barsread.h>
+#include <eikenv.h>
+#include <eikcmbut.h>
+#include <eikmsg.h>
+#include <gulcolor.h>
+#include <gulutil.h>
+#include <eikon.hrh>
+#include <eikmfne.pan>
+#include <eikmfne.h>
+#include <eikctl.rsg>
+#include <coecobs.h>
+#include <AknUtils.h>
+#include <avkon.hrh>
+#include <aknenv.h>
+
+// Skins drawing support
+#include <AknsDrawUtils.h>
+#include <aknappui.h>
+#include <AknSettingCache.h>
+#include <numberconversion.h>
+#include <aknsoundsystem.h>
+#include <AknTextDecorationMetrics.h>
+#include <AknLayoutFont.h>
+#include <AknBidiTextUtils.h>
+#include <aknextendedinputcapabilities.h>
+#include <fepbase.h>
+
+#include <AknTasHook.h>
+#include <eikdialg.h>
+
+#include <touchfeedback.h>
+
+// const TInt KMaxLatitudeDegrees=90;
+// const TInt KMaxLongitudeDegrees=180;
+const TInt KMaxMinSecValue=59;
+
+
+namespace EikMfneUtils
+ {
+ /**
+ IsAnyDigit, Is this a digit character any kind of numeral which can be mapped to 0-9?
+ @internalComponent
+ @return ETrue if this character is a numeral
+ @param aCharacter character to be tested
+ */
+ LOCAL_D TBool IsAnyDigit(TChar aCharacter)
+ {
+ return ( aCharacter.GetNumericValue() != KErrNotFound);
+ }
+ }
+
+enum
+ {
+ EGapAboveText=0,
+ EMfneFieldExtraHeight=2, // This constant is not used in Scalable UI
+ EGapBelowText=0,
+ EGapLeftOfFirstField=0,
+ EGapRightOfLastField=0,
+ EExtraHighlightHeight=0,
+ };
+
+// _LIT(KSpace," ");
+_LIT(KPlus,"+");
+_LIT(KMinus,"-");
+
+// global functions
+
+GLDEF_C TInt ExtraBaselineOffset()
+ {
+ TInt baselineOffset(0);
+ return baselineOffset;
+ }
+
+// For positioning mfne vertically to the correct position.
+GLDEF_C TInt VerticalOffsetForMfnePosition()
+ {
+ TAknLayoutId layout;
+ CAknEnv::Static()->GetCurrentLayoutId( layout );
+ return 0;
+ }
+
+GLDEF_C void Panic(TEikMfnePanic aPanic)
+ {
+ _LIT(KPanicCat,"EIKON-MFNE");
+ User::Panic(KPanicCat, aPanic);
+ }
+
+NONSHARABLE_CLASS(CEikMfneExtension) : public CBase, public MCoeFepAwareTextEditor
+ {
+public:
+ static CEikMfneExtension* NewL();
+ virtual ~CEikMfneExtension();
+
+// From MCoeFepAwareTextEditor
+public:
+ void StartFepInlineEditL( const TDesC &aInitialInlineText,
+ TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility,
+ const MFormCustomDraw *aCustomDraw,
+ MFepInlineTextFormatRetriever &aInlineTextFormatRetriever,
+ MFepPointerEventHandlerDuringInlineEdit
+ &aPointerEventHandlerDuringInlineEdit );
+
+ void UpdateFepInlineTextL( const TDesC &aNewInlineText,
+ TInt aPositionOfInsertionPointInInlineText );
+
+ void SetInlineEditingCursorVisibilityL( TBool aCursorVisibility );
+ void CancelFepInlineEdit();
+ TInt DocumentLengthForFep() const;
+ TInt DocumentMaximumLengthForFep() const;
+ void SetCursorSelectionForFepL(
+ const TCursorSelection &aCursorSelection );
+
+ void GetCursorSelectionForFep( TCursorSelection &aCursorSelection ) const;
+ void GetEditorContentForFep( TDes &aEditorContent, TInt aDocumentPosition,
+ TInt aLengthToRetrieve ) const;
+
+ void GetFormatForFep( TCharFormat &aFormat, TInt aDocumentPosition ) const;
+ void GetScreenCoordinatesForFepL( TPoint &aLeftSideOfBaseLine,
+ TInt &aHeight, TInt &aAscent, TInt aDocumentPosition ) const;
+
+private:
+ void DoCommitFepInlineEditL();
+ void FieldToSelection( TInt aField, TCursorSelection &aCursorSelection ) const;
+
+private:
+ CEikMfneExtension();
+ void ConstructL();
+
+public:
+ MAknsControlContext* iExternalSkinControlContext;
+ TInt iAknSkinColorIndex;
+ TInt iSkinIdForTextBackgroundColor;
+ CAknExtendedInputCapabilities* iExtendedInputCapabilities;
+ CEikMfne* iEditor; // not owned
+ CAknExtendedInputCapabilities::CAknExtendedInputCapabilitiesProvider*
+ iExtendedInputCapabilitiesProvider;
+ TInt iClipGcToRect; // Mainly for 0/1 values
+ TInt iDisablePenInput; // Mainly for 0/1 values
+ TBool iCursorShown;
+ TBool iFingerSupport;
+ TInt iFingerParam;
+ TBool iHighlightAll;
+ TBool iTouchActivated;
+ TCallBack iValidateValueCallBack;
+
+ MTouchFeedback* iFeedback;
+ TBool iLaunchPenInputAutomatic;
+ TBool iPartialScreenInput;
+ };
+
+// Implementation of the extension
+CEikMfneExtension* CEikMfneExtension::NewL()
+ {
+ CEikMfneExtension* self = new (ELeave) CEikMfneExtension();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CEikMfneExtension::~CEikMfneExtension()
+ {
+ delete iExtendedInputCapabilities;
+ delete iExtendedInputCapabilitiesProvider;
+ }
+
+CEikMfneExtension::CEikMfneExtension():iAknSkinColorIndex(KErrNotFound), iSkinIdForTextBackgroundColor(KErrNotFound)
+ , iFeedback(MTouchFeedback::Instance())
+ {
+ }
+
+void CEikMfneExtension::ConstructL()
+ {
+ iExtendedInputCapabilities = CAknExtendedInputCapabilities::NewL();
+ iExtendedInputCapabilitiesProvider =
+ new (ELeave) CAknExtendedInputCapabilities::CAknExtendedInputCapabilitiesProvider;
+
+ iExtendedInputCapabilitiesProvider->SetExtendedInputCapabilities(
+ iExtendedInputCapabilities );
+ }
+
+
+void CEikMfneExtension::StartFepInlineEditL( const TDesC &/*aInitialInlineText*/,
+ TInt /*aPositionOfInsertionPointInInlineText*/, TBool /*aCursorVisibility*/,
+ const MFormCustomDraw */*aCustomDraw*/,
+ MFepInlineTextFormatRetriever &/*aInlineTextFormatRetriever*/,
+ MFepPointerEventHandlerDuringInlineEdit
+ &/*aPointerEventHandlerDuringInlineEdit*/ )
+ {
+ // No implementation
+ }
+
+
+void CEikMfneExtension::UpdateFepInlineTextL( const TDesC &/*aNewInlineText*/,
+ TInt /*aPositionOfInsertionPointInInlineText*/ )
+ {
+ // No implementation
+ }
+
+
+void CEikMfneExtension::SetInlineEditingCursorVisibilityL( TBool /*aCursorVisibility*/ )
+ {
+ // No implementation
+ }
+
+
+void CEikMfneExtension::CancelFepInlineEdit()
+ {
+ // No implementation
+ }
+
+
+TInt CEikMfneExtension::DocumentLengthForFep() const
+ {
+ TInt documentLength( 0 );
+
+ // The fields' concrete Text() function must be
+ // properly implemented for this to work.
+ for ( TInt i = 0; i < iEditor->NumFields(); ++i )
+ {
+ documentLength += iEditor->Field( i )->FieldText().Length();
+ }
+
+ return documentLength;
+ }
+
+
+TInt CEikMfneExtension::DocumentMaximumLengthForFep() const
+ {
+ // We can't reach the field descriptors' MaxLength
+ // from here, as the implementations may vary
+ return DocumentLengthForFep();
+ }
+
+
+void CEikMfneExtension::SetCursorSelectionForFepL(
+ const TCursorSelection &aCursorSelection )
+ {
+ TInt documentLength( 0 );
+ TInt cursorPos = aCursorSelection.iCursorPos;
+ TInt i( 0 );
+ // The fields' concrete Text() function must be
+ // properly implemented for this to work.
+ for ( ; i < iEditor->NumFields(); ++i )
+ {
+ documentLength += iEditor->Field( i )->FieldText().Length();
+
+ if ( cursorPos <= documentLength )
+ {
+ if ( iEditor->Field( i )->IsEditable() )
+ {
+ iEditor->HighlightField( i );
+ break;
+ }
+ else
+ {
+ cursorPos++;
+ }
+ }
+ }
+
+ if ( iFingerSupport && iFingerParam == CEikMfne::EnableWithAllHighlight )
+ {
+ TBool oldHighlightAll( iHighlightAll );
+ iHighlightAll = ( aCursorSelection.Length() > documentLength &&
+ i == iEditor->NumFields() );
+ iTouchActivated = !iHighlightAll;
+ if ( oldHighlightAll != iHighlightAll )
+ {
+ CEikMfneField* currentField( iEditor->Field(
+ iEditor->CurrentField() ) );
+ if ( currentField->HighlightType() == CEikMfneField::ECursor )
+ {
+ const CFont& font=*( iEditor->Font() );
+ TBool dataAltered( EFalse );
+ TBool error( EFalse );
+ CEikonEnv* env( CEikonEnv::Static() );
+ currentField->HandleDeHighlight( font, *env, dataAltered,
+ error );
+ env->HideCursor( iEditor );
+ iCursorShown = EFalse;
+ }
+ iEditor->DrawDeferred();
+ iEditor->ReportUpdate();
+ if ( iHighlightAll )
+ {
+ iEditor->SetFirstEditableField();
+ }
+ }
+ if ( !iTouchActivated )
+ {
+ iValidateValueCallBack.CallBack();
+ iEditor->ReportStateChangeEventL();
+ }
+ }
+ }
+
+void CEikMfneExtension::FieldToSelection( TInt aField, TCursorSelection &aCursorSelection ) const
+ {
+ TInt fieldStart( 0 );
+ TInt fieldEnd( 0 );
+ TInt fieldIndex( 0 );
+
+ while ( fieldIndex < iEditor->NumFields() && fieldIndex <= aField )
+ {
+ fieldStart = fieldEnd;
+ fieldEnd += iEditor->Field( fieldIndex )->FieldText().Length();
+
+ if ( fieldIndex == aField )
+ {
+ aCursorSelection.SetSelection( fieldStart, fieldEnd );
+ }
+
+ fieldIndex++;
+ }
+ }
+
+void CEikMfneExtension::GetCursorSelectionForFep( TCursorSelection &aCursorSelection ) const
+ {
+ TInt currentField = iEditor->CurrentField();
+
+ // ENullIndex is private
+ if ( iFingerSupport && ( iFingerParam == CEikMfne::EnableWithAllHighlight ) &&
+ iHighlightAll )
+ {
+ aCursorSelection.SetSelection( 0, DocumentLengthForFep() );
+ }
+ else if ( currentField >= 0 && currentField < iEditor->NumFields() )
+ {
+ CEikMfneField* field = iEditor->Field( currentField );
+
+ FieldToSelection( currentField, aCursorSelection );
+
+ // If the field is not highlighted, we'll assume that the
+ // cursor is in the end of the field.
+ if ( field->HighlightType() == CEikMfneField::ECursor )
+ {
+ aCursorSelection.iCursorPos = aCursorSelection.iAnchorPos;
+ }
+ }
+ else
+ {
+ aCursorSelection.SetSelection( -1, -1 );
+ }
+ }
+
+
+void CEikMfneExtension::GetEditorContentForFep( TDes &aEditorContent, TInt aDocumentPosition,
+ TInt aLengthToRetrieve ) const
+ {
+ TInt length = DocumentLengthForFep();
+
+ HBufC* content = HBufC::New( length );
+ if ( content )
+ {
+ TPtr contentPtr = content->Des();
+
+ for ( TInt i = 0; i < iEditor->NumFields(); ++i )
+ {
+ contentPtr += iEditor->Field( i )->FieldText();
+ }
+
+ aEditorContent =
+ contentPtr.Mid( aDocumentPosition, aLengthToRetrieve );
+
+ delete content;
+ }
+ }
+
+
+void CEikMfneExtension::GetFormatForFep( TCharFormat &/*aFormat*/, TInt /*aDocumentPosition*/ ) const
+ {
+ // No implementation
+ }
+
+// FEP uses this function to get the coordinates of bottom of current cursor
+void CEikMfneExtension::GetScreenCoordinatesForFepL(
+ TPoint &aLeftSideOfBaseLine, TInt &aHeight, TInt &aAscent,
+ TInt /*aDocumentPosition*/ ) const
+ {
+ TInt cursorWidth( 0 );
+ iEditor->GetCursorInfo( aLeftSideOfBaseLine, aHeight, cursorWidth,
+ aAscent );
+ TPoint screenPos( iEditor->PositionRelativeToScreen() );
+ TPoint edwinPos = iEditor->Position();
+ aLeftSideOfBaseLine.iY += ( screenPos.iY - edwinPos.iY );
+ }
+
+void CEikMfneExtension::DoCommitFepInlineEditL()
+ {
+ // No implementation
+ }
+
+// CEikMfneField
+
+EXPORT_C CEikMfneField::CEikMfneField()
+ :iMinimumWidthInPixels(0)
+ {
+ __DECLARE_NAME(_S("CEikMfneField"));
+ }
+
+void CEikMfneField::Draw(CWindowGc& aGc, const CFont& aFont, const TPoint& aTopLeft) const
+ {
+ // Note that skin background drawing is currently performed in CEikMfne::DrawRange.
+ // So this is just responsible for text and (depending on highlighting) the highlight block
+ TInt topMargin(0);
+ TInt bottomMargin(0);
+ TInt extraHeight(0);
+ TAknTextDecorationMetrics metrics( &aFont );
+ metrics.GetTopAndBottomMargins( topMargin, bottomMargin );
+ extraHeight = topMargin + bottomMargin;
+ const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( &aFont );
+ TInt textPaneHeight(0);
+ TInt textPaneAscent(0);
+
+ // Get the pane metrics from the best source of information
+ if ( layoutFont )
+ {
+ textPaneHeight = layoutFont->TextPaneHeight();
+ textPaneAscent = layoutFont->TextPaneTopToBaseline();
+ }
+ else
+ {
+ textPaneHeight = aFont.HeightInPixels();
+ textPaneAscent = aFont.AscentInPixels();
+ }
+
+ // This is similar to TAknLayoutText's draw, but includes margins.
+ // Text and background are draw in one operation. Positioning of the text horizontally
+ // w.r.t. aTopMargin is done with the "aLeftMargin" parameter. Horizontal extent is
+ // controlled by the width of the "aBox" parameter
+ TInt leftMargin(0);
+ TInt rightMargin(0);
+ metrics.GetLeftAndRightMargins( leftMargin, rightMargin );
+
+ // Convert the text to visual
+ TInt textWidth = WidthInPixels( aFont );
+ TPtrC drawText = Text();
+ HBufC* visualText = HBufC::New( drawText.Length() + KAknBidiExtraSpacePerLine );
+
+ if ( visualText )
+ {
+ TPtr visualTextPtr = visualText->Des();
+
+ AknBidiTextUtils::ConvertToVisualAndClip(
+ drawText,
+ visualTextPtr,
+ aFont,
+ textWidth,
+ textWidth,
+ AknBidiTextUtils::EImplicit,
+ 0xFFFF ); // no clipping char
+
+ drawText.Set( *visualText );
+ }
+
+ aGc.DrawText( drawText,
+ TRect( aTopLeft, // top left. Should be control top left
+ TSize( textWidth, //width
+ textPaneHeight + extraHeight )), // total height
+ textPaneAscent + topMargin, // distance from top to baseline
+ CGraphicsContext::ECenter); // alignment to center
+
+ delete visualText;
+ }
+
+TInt CEikMfneField::WidthInPixels(const CFont& aFont) const
+ {
+ return Max( iMinimumWidthInPixels, aFont.TextWidthInPixels(Text()) + AdditionalWidthForHighlights(aFont) );
+ }
+
+TInt CEikMfneField::DistanceFromStartOfFieldToEndOfTextInPixels(const CFont& aFont) const
+ {
+ // Approximation is that the spacing in glyphs is on the right. Therefore the additional spacing will
+ // have been put on the left. See the draw routine call in CEikMMfneField::Draw
+ TInt textwidth = aFont.TextWidthInPixels(Text());
+ return textwidth + AdditionalWidthForHighlights(aFont)+ (WidthInPixels(aFont)-textwidth)/2;
+ }
+
+EXPORT_C TBool CEikMfneField::IsEditable() const
+ {
+ return EFalse;
+ }
+
+EXPORT_C TBool CEikMfneField::IsValid() const
+ {
+ return ETrue;
+ }
+
+EXPORT_C CEikMfneField::THighlightType CEikMfneField::HighlightType() const
+ {
+#if defined(_DEBUG)
+ Panic(EEikPanicMfneFieldIsNotEditable1);
+#endif
+ return EInverseVideo; // dummy return to prevent compiler error
+ }
+
+EXPORT_C void CEikMfneField::HandleKey(const CFont&, const TKeyEvent&, TBool, TBool&, TInt&)
+ {
+#if defined(_DEBUG)
+ Panic(EEikPanicMfneFieldIsNotEditable2);
+#endif
+ }
+
+EXPORT_C void CEikMfneField::HandleDeHighlight(const CFont&, CEikonEnv&, TBool&, TBool&)
+ {
+#if defined(_DEBUG)
+ Panic(EEikPanicMfneFieldIsNotEditable3);
+#endif
+ }
+
+EXPORT_C void CEikMfneField::HandleLeftOrRightArrow(TChar aKey, TBool& aDataAltered, TInt& aHighlightIncrement)
+ {
+ __ASSERT_DEBUG((aKey==EKeyLeftArrow) || (aKey==EKeyRightArrow), Panic(EEikPanicMfneArrowKeyExpected));
+ aHighlightIncrement=(aKey==EKeyLeftArrow)? -1: 1;
+ aDataAltered=ETrue;
+ }
+
+TInt CEikMfneField::AdditionalWidthForHighlights(const CFont& aFont) const
+ {
+ TInt addedWidth(0);
+ if ( IsEditable() )
+ {
+ TInt rightHighlight(0);
+ TAknTextDecorationMetrics metrics( &aFont );
+ // Width is increased only by leftHighlight. This is a compromise in that glyphs already have
+ // spacing within them to achieve character spacing. This spacing is generally (for numbers) on the right.
+ metrics.GetLeftAndRightMargins( addedWidth, rightHighlight ); // rightHighlight is not used
+ }
+ return addedWidth;
+ }
+
+const TDesC& CEikMfneField::FieldText() const
+ {
+ return Text();
+ }
+
+// CEikMfneSeparator
+
+CEikMfneSeparator::CEikMfneSeparator(HBufC* aText)
+ :iText(aText)
+ {
+ __DECLARE_NAME(_S("CEikMfneSeparator"));
+ }
+
+EXPORT_C CEikMfneSeparator::~CEikMfneSeparator()
+ {
+ delete iText;
+ }
+
+EXPORT_C CEikMfneSeparator* CEikMfneSeparator::NewL(TResourceReader& aResourceReader)
+ {
+ HBufC* text=aResourceReader.ReadHBufCL();
+ CleanupStack::PushL(text);
+ CEikMfneSeparator* separator=NewL(text);
+ CleanupStack::Pop();
+ return separator;
+ }
+
+EXPORT_C CEikMfneSeparator* CEikMfneSeparator::NewL(HBufC* aText)
+ {
+ return new(ELeave) CEikMfneSeparator(aText);
+ }
+
+EXPORT_C void CEikMfneSeparator::SetText(HBufC* aText)
+ {
+ __ASSERT_ALWAYS(iText==NULL, Panic(EEikPanicMfneSeparatorTextHasAlreadyBeenSet));
+ iText=aText;
+ }
+
+TInt CEikMfneSeparator::MaximumWidthInPixels(const CFont& aFont, TBool)
+ {
+ return aFont.TextWidthInPixels(*iText)+AdditionalWidthForHighlights(aFont);
+ }
+
+TCoeInputCapabilities CEikMfneSeparator::InputCapabilities() const
+ {
+ return TCoeInputCapabilities(TCoeInputCapabilities::ENone);
+ }
+
+const TDesC& CEikMfneSeparator::Text() const
+ {
+ return *iText;
+ }
+
+
+
+// CEikMfneNumber
+
+CEikMfneNumber::CEikMfneNumber(TInt aMinimumValue, TInt aMaximumValue, TUint32 aFlags)
+ :iMinimumValue(aMinimumValue),
+ iMaximumValue(aMaximumValue),
+ iFlags(aFlags),
+ iDigitType(EDigitTypeWestern)
+ {
+ TBuf<16> minText;
+ minText.AppendNum(aMinimumValue);
+ TBuf<16> maxText;
+ maxText.AppendNum(aMaximumValue);
+ iMaxDigits=Max(minText.Length(),maxText.Length());
+
+ iMaxDigitsMinimumValue=minText.Length();
+ iMaxDigitsMaximumValue=maxText.Length();
+
+ __DECLARE_NAME(_S("CEikMfneNumber"));
+ __ASSERT_ALWAYS(aMinimumValue<=aMaximumValue, Panic(EEikPanicMfneBadNumberMinimumAndMaximum1));
+ __ASSERT_ALWAYS((aFlags&~EPublicallySettableFlags)==0, Panic(EEikPanicMfneBadNumberFlags));
+ }
+
+EXPORT_C CEikMfneNumber::~CEikMfneNumber()
+ {
+ delete iText;
+ }
+
+EXPORT_C CEikMfneNumber* CEikMfneNumber::NewL(const CFont& aFont, TResourceReader& aResourceReader)
+ {
+#pragma warning (disable : 4127)
+ __ASSERT_DEBUG((EFillWithLeadingZeros==EEikMfneNumberFlagFillWithLeadingZeros) &&
+ (EPreserveOldWidthBeforeEditing==EEikMfneNumberFlagPreserveOldWidthBeforeEditing) &&
+ (EFillWithLeadingZeros==EEikMfneNumberFlagFillWithLeadingZeros), Panic(EEikPanicMfneInconsistentNumberFlags));
+#pragma warning (default : 4127)
+ TInt minimumValue=aResourceReader.ReadInt32();
+ TInt maximumValue=aResourceReader.ReadInt32();
+ TUint32 flags=aResourceReader.ReadUint8();
+ return NewL(aFont, minimumValue, maximumValue, maximumValue, flags);
+ }
+
+EXPORT_C CEikMfneNumber* CEikMfneNumber::NewL(const CFont& aFont, TInt aMinimumValue, TInt aMaximumValue, TInt aInitialValue, TUint32 aFlags)
+ {
+ __ASSERT_ALWAYS((aInitialValue>=aMinimumValue) && (aInitialValue<=aMaximumValue), Panic(EEikPanicMfneBadNumberMinimumAndMaximum2));
+ CEikMfneNumber* number=new(ELeave) CEikMfneNumber(aMinimumValue, aMaximumValue, aFlags);
+ CleanupStack::PushL(number);
+ number->iText=HBufC::NewL(number->MaximumNumberOfDigits()+((aMinimumValue<0)? 1: 0));
+ number->SetValue(aInitialValue, aFont);
+ number->ConstructL();
+ CleanupStack::Pop();
+ return number;
+ }
+
+void CEikMfneNumber::ConstructL()
+ {
+ CEikonEnv* eikEnv=CEikonEnv::Static();
+ iNudgeCharMinus=eikEnv->NudgeCharMinus();
+ iNudgeCharPlus=eikEnv->NudgeCharPlus();
+ }
+
+EXPORT_C void CEikMfneNumber::SetMinimumAndMaximum(TInt aMinimumValue, TInt aMaximumValue, const CFont& aFont)
+ {
+ TBuf<16> minText;
+ minText.AppendNum(aMinimumValue);
+ TBuf<16> maxText;
+ maxText.AppendNum(aMaximumValue);
+ TInt minTextLength=minText.Length();
+ TInt maxTextLength=maxText.Length();
+ __ASSERT_ALWAYS((aMinimumValue<=aMaximumValue) &&
+ (minTextLength<=iMaxDigits) &&
+ (maxTextLength<=iMaxDigits), Panic(EEikPanicMfneBadNumberMinimumAndMaximum3));
+ //__ASSERT_ALWAYS((aMinimumValue<=aMaximumValue) &&
+ // (aMinimumValue>=iMinimumValueCateredForInFieldWidth) &&
+ // (aMaximumValue<=iMaximumValueCateredForInFieldWidth), Panic(EEikPanicMfneBadNumberMinimumAndMaximum3));
+ iMinimumValue=aMinimumValue;
+ iMaximumValue=aMaximumValue;
+ TInt value=ValueFromText();
+ if (value<aMinimumValue||!NumberOfDigits())
+ SetTextToValue(aMinimumValue, aFont);
+ else if (value>aMaximumValue)
+ SetTextToValue(aMaximumValue, aFont);
+ }
+
+EXPORT_C void CEikMfneNumber::GetMinimumAndMaximum(TInt& aMinimumValue, TInt& aMaximumValue) const
+ {
+ aMinimumValue=iMinimumValue;
+ aMaximumValue=iMaximumValue;
+ }
+
+EXPORT_C void CEikMfneNumber::SetValue(TInt aValue, const CFont& aFont)
+ {
+ // This is part of the trailing zeros and TInt fix. We have to do this to
+ // allow setting values like "050" by passing 50 to this function in case
+ // the trailing zeros are on.
+ if ( iFlags & EFillWithTrailingZeros )
+ {
+ TInt val = aValue;
+ TInt count = 0;
+ for(;val;val/=10) count ++;
+ if (MaximumNumberOfDigits()-count < 0) count = MaximumNumberOfDigits();
+ iText->Des().Fill( TText('1'), MaximumNumberOfDigits() );
+ iText->Des().Fill( ZeroCharacter(), MaximumNumberOfDigits() - count);
+ }
+
+ SetTextToValue(aValue, aFont);
+ }
+
+EXPORT_C TInt CEikMfneNumber::Value() const
+ {
+ TInt value( -1 );
+ if (NumberOfDigits() > 0)
+ {
+ value = ValueFromText();
+ }
+ if (value < iMinimumValue)
+ {
+ value = iMinimumValue;
+ }
+ if (value > iMaximumValue)
+ {
+ value = iMaximumValue;
+ }
+ return value;
+ }
+
+EXPORT_C TBool CEikMfneNumber::IsValid() const
+ {
+ return (NumberOfDigits() != 0);
+ }
+
+TChar CEikMfneNumber::NormalizeDigit(TChar aChar)
+/**
+NormalizeDigit
+Normalises a character to the current digit type.
+@internalComponent
+@return TChar of if this character is a numeral
+@param aCharacter character to be tested
+*/
+ {
+ TBuf<1> buf;
+ buf.Append(aChar);
+ NumberConversion::ConvertDigits(buf, iDigitType);
+ return buf[0];
+ }
+
+TText CEikMfneNumber::ZeroCharacter() const
+ {
+ return TText(iDigitType);
+ }
+
+TText CEikMfneNumber::NegativeCharacter() const
+ {
+ return TText('-');
+ }
+
+TBool CEikMfneNumber::IsTextNull() const
+ {
+ return ( Text().Length() < 1 );
+ }
+
+TInt CEikMfneNumber::MaximumWidthInPixels(const CFont& aFont, TBool aShrinkToMinimumSize)
+ {
+ if (aShrinkToMinimumSize)
+ {
+ //iMinimumValueCateredForInFieldWidth=iMinimumValue;
+ //iMaximumValueCateredForInFieldWidth=iMaximumValue;
+ TBuf<16> minText;
+ minText.AppendNum(iMinimumValue);
+ TBuf<16> maxText;
+ maxText.AppendNum(iMaximumValue);
+
+ iMaxDigits=Max(2,Max(minText.Length(),maxText.Length()));
+ }
+ return (MaximumNumberOfDigits()*TFindWidthOfWidestDigitType(DigitType()).MaximumWidthInPixels(aFont)) + AdditionalWidthForHighlights(aFont) /*+((iMinimumValueCateredForInFieldWidth<0)? aFont.TextWidthInPixels(_L("-")): 0)*/;
+ }
+
+TCoeInputCapabilities CEikMfneNumber::InputCapabilities() const
+ {
+ TUint inputCapabilities=TCoeInputCapabilities::ENone;
+ if (iMinimumValue<0)
+ {
+ inputCapabilities|=TCoeInputCapabilities::EWesternNumericIntegerNegative;
+ }
+ if (iMaximumValue>0)
+ {
+ inputCapabilities|=TCoeInputCapabilities::EWesternNumericIntegerPositive;
+ }
+ return TCoeInputCapabilities(inputCapabilities);
+ }
+
+const TDesC& CEikMfneNumber::Text() const
+ {
+ if (IsUninitialised())
+ return KNullDesC();
+ else
+ return *iText;
+ }
+
+TBool CEikMfneNumber::IsEditable() const
+ {
+ return ETrue;
+ }
+
+CEikMfneField::THighlightType CEikMfneNumber::HighlightType() const
+ {
+ return (iFlags&EIsBeingEditedWithCursor)? ECursor: EInverseVideo;
+ }
+
+void CEikMfneNumber::HandleKey(const CFont& aFont, const TKeyEvent& aKeyEvent, TBool aInterpretLeftAndRightAsEarEvents, TBool& aDataAltered, TInt& aHighlightIncrement)
+ {
+ TChar ch=aKeyEvent.iCode;
+
+ TPtr text=iText->Des();
+ TInt textLength=text.Length();
+ TBool nudgeTen=EFalse;
+ switch (ch)
+ {
+ case EKeyLeftArrow:
+ case EKeyRightArrow:
+ if (!aInterpretLeftAndRightAsEarEvents)
+ HandleLeftOrRightArrow(ch, aDataAltered, aHighlightIncrement);
+ else
+ {
+ const TInt nudge=(nudgeTen? 10 : 1);
+ TInt newValue;
+
+
+ if ((textLength==0) || ! EikMfneUtils::IsAnyDigit( TChar(text[textLength-1]) ) )
+ newValue=0;
+ else
+ newValue=ValueFromText()+((ch==EKeyLeftArrow)? -nudge: nudge);
+ if (newValue>=iMaximumValue)
+ newValue=iMaximumValue;
+ else if (newValue<=iMinimumValue)
+ newValue=iMinimumValue;
+ SetTextToValue(newValue, aFont);
+ aHighlightIncrement=0;// Always highlight the field being nudged
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+ iFlags&=~EIsBeingEditedWithCursor;
+ }
+ break;
+ case EKeyDownArrow:
+ case EKeyUpArrow:
+ {
+ if (IsUninitialised())
+ {
+ SetUninitialised(EFalse);
+ }
+ else
+ {
+ const TInt nudge=(nudgeTen? 10 : 1);
+ TInt newValue;
+
+
+ if ((textLength==0) || ! EikMfneUtils::IsAnyDigit( TChar(text[textLength-1])) )
+ newValue=0;
+ else
+ newValue=ValueFromText()+((ch==EKeyDownArrow)? -nudge: nudge);
+
+ if (newValue>iMaximumValue)
+ newValue=iMinimumValue;
+ else if (newValue<iMinimumValue)
+ newValue=iMaximumValue;
+ SetTextToValue(newValue, aFont);
+ aHighlightIncrement=0;// Always highlight the field being nudged
+ aDataAltered=ETrue;
+ iFlags&=~EIsBeingEditedWithCursor;
+ }
+ aDataAltered=ETrue;
+ }
+ break;
+ case EKeyBackspace:
+ if (textLength)
+ {
+ if (iFlags&EIsBeingEditedWithCursor)
+ {
+ text.SetLength(textLength-1);
+ }
+ else
+ {
+ iFlags|=EIsBeingEditedWithCursor;
+ text.SetLength(0);
+ }
+ if (text==KMinus)
+ text.SetLength(0);
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+ }
+ break;
+ case '+':
+ break;
+ case '-':
+ if (iMinimumValue < 0)
+ {
+ if (~iFlags&EIsBeingEditedWithCursor)
+ {
+ iFlags|=EIsBeingEditedWithCursor;
+ text.SetLength(0);
+ }
+ if (text.Length()==0)
+ {
+ text.Append('-');
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+ }
+ }
+ break;
+ default:
+ if ( EikMfneUtils::IsAnyDigit(ch) )
+ {
+ if (~iFlags&EIsBeingEditedWithCursor)
+ {
+ iFlags|=EIsBeingEditedWithCursor;
+ text.SetLength(0);
+ }
+ __ASSERT_DEBUG(NumberOfDigits()<MaximumNumberOfDigits(),Panic(EEikPanicMfneNumberTextInBadState));
+ text.Append(NormalizeDigit(ch) );
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+
+ // Space reserved for minus sign is not supposed to be shown, so if
+ // the value is >= 0 we must subtract the space for minus in case
+ // the minimum possible value is negative..
+ if ( NumberOfDigits() >=
+ ( ValueFromText() >= 0 && iMinimumValue < 0 ? MaximumNumberOfDigits() - 1 : MaximumNumberOfDigits() ) )
+ {
+ aHighlightIncrement=1;
+ }
+ }
+ break;
+ }
+ }
+
+void CEikMfneNumber::HandleDeHighlight(const CFont& aFont, CEikonEnv& aEikonEnv, TBool& aDataAltered, TBool& aError)
+ {
+ iFlags&=~EIsBeingEditedWithCursor;
+ if (NumberOfDigits()==0)
+ {
+ SetTextToValue(iMinimumValue, aFont);
+ aDataAltered=ETrue;
+ aError=ETrue;
+ aEikonEnv.InfoMsg(R_EIK_TBUF_NO_NUMBER_ENTERED);
+ return;
+ }
+ TInt value=ValueFromText();
+ if ((value<iMinimumValue) || (value>iMaximumValue))
+ {
+ TBool succeeded = ConvertsIntoValidValue(value);
+ if ( !succeeded )
+ {
+ aDataAltered=ETrue;
+ aError=ETrue;
+ if (value<iMinimumValue)
+ {
+ SetTextToValue(iMinimumValue, aFont);
+ CEikMfne::InvalidFieldAlert();
+ aEikonEnv.InfoMsg(R_EIK_TBUF_NUMBER_BELOW_MIN, iMinimumValue);
+ return;
+ }
+ if (value>iMaximumValue)
+ {
+ CEikMfne::InvalidFieldAlert();
+ SetTextToValue(iMaximumValue, aFont);
+ aEikonEnv.InfoMsg(R_EIK_TBUF_NUMBER_ABOVE_MAX, iMaximumValue);
+ return;
+ }
+ }
+ }
+ TBuf<128> oldText=*iText;
+ TBool unInit = IsUninitialised();
+ SetTextToValue(value, aFont);
+ if (oldText!=*iText)
+ aDataAltered=ETrue;
+ else
+ SetUninitialised(unInit);
+ }
+
+TInt CEikMfneNumber::MaximumNumberOfDigits() const
+ {
+ return Max(2,iMaxDigits);
+ }
+
+TInt CEikMfneNumber::NumberOfDigits() const
+ {
+ return iText->Length();
+ }
+
+void CEikMfneNumber::SetTrailingZeros()
+ {
+ iFlags |= EFillWithTrailingZeros;
+ }
+
+void CEikMfneNumber::SetTextToValue(TInt aValue, const CFont& /*aFont*/)
+ {
+ __ASSERT_DEBUG((aValue>=iMinimumValue) && (aValue<=iMaximumValue), Panic(EEikPanicMfneNumberOutsidePermittedRange));
+
+ SetUninitialised(EFalse);
+
+ TPtr textPtr = iText->Des();
+ TInt maxNumbers = MaximumNumberOfDigits();
+ TInt leadingZeros = 0;
+ TText zeroChar = ZeroCharacter();
+ TText negChar = NegativeCharacter();
+
+ // The problem here is that we have no way of knowing through TInt aValue
+ // if the number that is wanted is 005, 05, or 5. That would be fine
+ // as long as trailing zeros are not used, but with the trailing
+ // zeros one has to be able to enter "050" by typing just "05".
+ // When this is typed and the field changes, this function gets called with
+ // aValue of 5, and we don't know if that should really be "500", "050" or
+ // "005", because all those values could be possible in a number with
+ // trailing zeros. The following tries to overcome this limitation..
+ TLex lex( textPtr );
+ TChar chr;
+
+ while ( chr = lex.Get() )
+ {
+ if ( chr == zeroChar )
+ {
+ leadingZeros++;
+ }
+ else if ( chr != negChar )
+ {
+ break; // We break at first char that's not '-' or zero
+ }
+ }
+
+ textPtr.SetLength( 0 );
+
+ if ( iMinimumValue < 0 )
+ {
+ maxNumbers--;
+
+ // Has to be done here, because we have to pad between
+ // the negative char and the number.
+ if ( aValue < 0 )
+ {
+ textPtr.Append( negChar );
+ aValue = -aValue;
+ }
+ }
+
+ // From this on we deal with western digits, and convert at the end
+ zeroChar = TText( '0' );
+
+ if ( iFlags & EFillWithTrailingZeros ) // trailing takes precedence
+ {
+ HBufC* formatStringBuf = HBufC::New( leadingZeros + 10 );
+
+ if ( !formatStringBuf )
+ {
+ textPtr.Num( aValue );
+ }
+ else
+ {
+ TPtr formatString = formatStringBuf->Des();
+
+ if ( aValue != 0 && leadingZeros )
+ {
+ formatString.Fill( zeroChar, leadingZeros );
+ maxNumbers -= leadingZeros;
+ }
+
+ _LIT( KFormatString, "%-**d" );
+ formatString.Append( KFormatString );
+ textPtr.AppendFormat( formatString, zeroChar, maxNumbers, aValue );
+ delete formatStringBuf;
+ }
+ }
+ else if ( iFlags & EFillWithLeadingZeros )
+ {
+ _LIT( KFormatString, "%+**d" );
+ textPtr.Format( KFormatString, zeroChar, maxNumbers, aValue );
+ }
+ else
+ {
+ textPtr.Num( aValue );
+ }
+
+ NumberConversion::ConvertDigits( textPtr, iDigitType );
+
+ if ( iFlags & EPreserveOldWidthBeforeEditing )
+ {
+ iMinimumWidthInPixels = 0; //WidthInPixels(aFont);
+ }
+ }
+
+TInt CEikMfneNumber::ValueFromText() const
+ {
+// __ASSERT_DEBUG(NumberOfDigits(), Panic(EEikPanicMfneNumberHasNoDigits));
+ if (!NumberOfDigits())
+ return iMinimumValue;
+ TInt i=0;
+ TInt valueFromText=0;
+ TBool isNegative=EFalse;
+ switch ((*iText)[i])
+ {
+ case '-':
+ ++i;
+ isNegative=ETrue;
+ break;
+ }
+ TInt textLength=iText->Length();
+ for (; i<textLength; ++i)
+ {
+ TText digit=(*iText)[i];
+ __ASSERT_DEBUG(EikMfneUtils::IsAnyDigit( TChar(digit)), Panic(EEikPanicMfneDigitExpected));
+ if (i>=textLength-2)
+ {
+ if (!isNegative && valueFromText>(KMaxTInt32/10))
+ return KMaxTInt32;
+ else if (isNegative && (-valueFromText)<(KMinTInt32/10))
+ return KMinTInt32;
+ }
+ valueFromText=(valueFromText*10)+(TInt)(digit-ZeroCharacter());
+ }
+ if (isNegative==EFalse && valueFromText<0)
+ return KMaxTInt32;// Deals with overflow
+ if (isNegative)
+ valueFromText=-valueFromText;
+ return valueFromText;
+ }
+
+TBool CEikMfneNumber::ConvertsIntoValidValue(TInt& aValue) const
+ {
+ if ((iFlags&ERepresentsYear) && (aValue>=0) && (aValue<100))
+ {
+ TTime homeTime;
+ homeTime.HomeTime();
+ TInt currentYear=homeTime.DateTime().Year();
+ if (currentYear>0)
+ {
+ TInt yearsSinceStartOfCurrentCentury=currentYear%100;
+ TInt newValue=(currentYear-yearsSinceStartOfCurrentCentury)+aValue;
+ // If two digit year is given, 2000 + aValue is expected.
+ aValue=newValue;
+ if ((newValue>=iMinimumValue) && (newValue<=iMaximumValue))
+ {
+ return ETrue;
+ }
+ }
+ }
+ return EFalse;
+ }
+
+EXPORT_C void CEikMfneNumber::SetUninitialised(TBool aUninitialised)
+ {
+ if (aUninitialised)
+ iFlags |= EIsUninitialised;
+ else
+ iFlags &= ~EIsUninitialised;
+ }
+
+EXPORT_C TBool CEikMfneNumber::IsUninitialised() const
+ {
+ return iFlags & EIsUninitialised;
+ }
+
+
+EXPORT_C void CEikMfneNumber::RefreshDigitType( const CFont& aFont)
+/**
+Derive digit display type from locale information. This call sets the digit type based on current device settings.
+It can be called after construction to make the field display correct numeral (if it is required.
+Or can be called any number of times in response to Tlocale change. For dynamic update.
+@publishedComponent
+@since 2.0
+@lib eikctl.lib
+@param a locale structure which will be used to decide on the digit display.
+@param aFont the font of the MFNE which owns this class
+@post the next time the field is drawn it will display the number using digit type derived from the locale information.
+*/
+ {
+ SetDigitType( AknTextUtils::NumericEditorDigitType(), aFont);
+ }
+
+EXPORT_C void CEikMfneNumber::SetDigitType(TDigitType aDigitType, const CFont& aFont)
+/**
+Set Numeral Type for displaying Numbers type for International digit support
+@publishedComponent
+@since 2.0
+@lib eikctl.lib
+@param aDigitType Set the numeral type for this field to display numbers in.
+@param aFont the font of the MFNE which owns this class
+@post the next time the field is drawn it will display the number using the supplied digit type.
+*/
+ {
+ TInt value = Value();
+ iDigitType = aDigitType;
+ SetTextToValue(value, aFont);
+ }
+
+EXPORT_C TDigitType CEikMfneNumber::DigitType() const
+/**
+retrieve the current numeral type of the field
+@publishedComponent
+@since 2.0
+@lib eikctl.lib
+@return the current numeral display type.
+*/
+ {
+ return iDigitType;
+ }
+
+// CEikMfneSymbol
+
+CEikMfneSymbol::CEikMfneSymbol(TInt aNumSymbolicItems)
+ :iNumSymbolicItems(aNumSymbolicItems),
+ iCurrentSymbolicItem(0)
+ {
+ __DECLARE_NAME(_S("CEikMfneSymbol"));
+ __ASSERT_ALWAYS(aNumSymbolicItems>1, Panic(EEikPanicMfneTooFewSymbolicItems));
+ }
+
+EXPORT_C CEikMfneSymbol::~CEikMfneSymbol()
+ {
+ if (iSymbolicItems)
+ {
+ for (TInt i=0; i<iNumSymbolicItems; ++i)
+ delete iSymbolicItems[i];
+ delete [] iSymbolicItems;
+ }
+ }
+
+EXPORT_C CEikMfneSymbol* CEikMfneSymbol::NewL(TResourceReader& aResourceReader)
+ {
+ TInt numSymbols=aResourceReader.ReadUint8();
+ CEikMfneSymbol* symbol=NewL(numSymbols);
+ CleanupStack::PushL(symbol);
+ for (TInt i=0; i<numSymbols; ++i)
+ symbol->AddSymbolicItem(CItem::NewL(aResourceReader), i==0);
+ CleanupStack::Pop();
+ return symbol;
+ }
+
+EXPORT_C CEikMfneSymbol* CEikMfneSymbol::NewL(TInt aNumSymbolicItems)
+ {
+ CEikMfneSymbol* symbol=new(ELeave) CEikMfneSymbol(aNumSymbolicItems);
+ CleanupStack::PushL(symbol);
+ symbol->iSymbolicItems=new(ELeave) CItem*[aNumSymbolicItems];
+ for (TInt i=0; i<aNumSymbolicItems; ++i)
+ symbol->iSymbolicItems[i]=NULL;
+ CleanupStack::Pop();
+ return symbol;
+ }
+
+EXPORT_C void CEikMfneSymbol::AddSymbolicItem(CItem* aSymbolicItem, TBool aMakeCurrent)
+ {
+ __ASSERT_DEBUG(iSymbolicItems, Panic(EEikPanicMfneSymbolicItemArrayNotCreated));
+ for (TInt i=0; i<iNumSymbolicItems; ++i)
+ if (iSymbolicItems[i]==NULL)
+ {
+ iSymbolicItems[i]=aSymbolicItem;
+ if (aMakeCurrent)
+ SetCurrentSymbolicItem(i);
+ return;
+ }
+#if defined(_DEBUG)
+ Panic(EEikPanicMfneTooManySymbolicItemsAdded);
+#endif
+ }
+
+EXPORT_C void CEikMfneSymbol::SetCurrentSymbolicItemToId(TInt aId)
+ {
+ for (TInt i=0; i<iNumSymbolicItems; ++i)
+ if (iSymbolicItems[i]->iId==aId)
+ {
+ SetCurrentSymbolicItem(i);
+ SetUninitialised(EFalse);
+ return;
+ }
+#if defined(_DEBUG)
+ Panic(EEikPanicMfneIdOfSymbolicItemNotFound);
+#endif
+ }
+
+EXPORT_C TInt CEikMfneSymbol::IdOfCurrentSymbolicItem() const
+ {
+ return iSymbolicItems[CurrentSymbolicItem()]->iId;
+ }
+
+TInt CEikMfneSymbol::MaximumWidthInPixels(const CFont& aFont, TBool)
+ {
+ TInt maximumWidthInPixels=0;
+ for (TInt i=0; i<iNumSymbolicItems; ++i)
+ {
+ TInt widthInPixels=aFont.TextWidthInPixels(*iSymbolicItems[i]->iText);
+ if (maximumWidthInPixels<widthInPixels)
+ maximumWidthInPixels=widthInPixels;
+ }
+
+ /* In the uninitialised state iMinimumWidthInPixels is set to the max with so that when focussed in the uninitialised state the
+ * whole space is highlighted. Note that when the state becomes not uninitialised iMinimumwidth... is set back to zero.
+ */
+ if (IsUninitialised())
+ iMinimumWidthInPixels = maximumWidthInPixels + AdditionalWidthForHighlights(aFont);
+ else
+ iMinimumWidthInPixels = 0;
+ return maximumWidthInPixels;
+ }
+
+TCoeInputCapabilities CEikMfneSymbol::InputCapabilities() const
+ {
+ TUint inputCapabilities=TCoeInputCapabilities::EWesternAlphabetic;
+ for (TInt i=0; i<iNumSymbolicItems; ++i)
+ {
+ const TCharF keyToMatch=iSymbolicItems[i]->iKeyToMatch;
+ if ((keyToMatch<TCharF('A')) || (keyToMatch>TCharF('Z'))) // a crude test, but it's probably sufficient
+ {
+ inputCapabilities=TCoeInputCapabilities::EAllText;
+ }
+ }
+ return TCoeInputCapabilities(inputCapabilities);
+ }
+
+const TDesC& CEikMfneSymbol::Text() const
+ {
+ if (IsUninitialised())
+ return KNullDesC();
+ else
+ return *iSymbolicItems[CurrentSymbolicItem()]->iText;
+ }
+
+TBool CEikMfneSymbol::IsEditable() const
+ {
+ return ETrue;
+ }
+
+CEikMfneField::THighlightType CEikMfneSymbol::HighlightType() const
+ {
+ return EInverseVideo;
+ }
+
+void CEikMfneSymbol::HandleKey(const CFont&, const TKeyEvent& aKeyEvent, TBool, TBool& aDataAltered, TInt& aHighlightIncrement)
+ {
+ TChar ch=aKeyEvent.iCode;
+ switch (ch)
+ {
+ case EKeyLeftArrow:
+ case EKeyRightArrow:
+ HandleLeftOrRightArrow(ch, aDataAltered, aHighlightIncrement);
+ break;
+ case EKeyPowerOff:
+ case EKeyPhoneEnd:
+ case EKeyApplication:
+ break;
+ default:
+ if (IsUninitialised())
+ SetUninitialised(EFalse);
+ else
+ SetCurrentSymbolicItem((CurrentSymbolicItem()+1)%iNumSymbolicItems);
+ aDataAltered=ETrue;
+ break;
+ }
+ }
+
+void CEikMfneSymbol::HandleDeHighlight(const CFont&, CEikonEnv&, TBool&, TBool&)
+ {
+ }
+
+
+
+/*
+ * The unilitialised flag uses the topmost bit of iCurrentSymbolicItem. This is to preserve the size of the class for BC.
+ * It's important that iCurrentSymbolic item is never negative though as it is an index that should not happen.
+ *
+ */
+const TInt KMfneSymbolUninitialisedBit = 0xf0000000;
+EXPORT_C void CEikMfneSymbol::SetUninitialised(TBool aUninitialised)
+ {
+ if (aUninitialised)
+ {
+ iCurrentSymbolicItem |= KMfneSymbolUninitialisedBit;
+ }
+ else
+ {
+ iCurrentSymbolicItem &= ~KMfneSymbolUninitialisedBit;
+ iMinimumWidthInPixels = 0;
+ }
+ }
+
+EXPORT_C TBool CEikMfneSymbol::IsUninitialised() const
+ {
+ return iCurrentSymbolicItem & KMfneSymbolUninitialisedBit;
+ }
+
+TInt CEikMfneSymbol::CurrentSymbolicItem() const
+ {
+ return iCurrentSymbolicItem & ~KMfneSymbolUninitialisedBit;
+ }
+
+void CEikMfneSymbol::SetCurrentSymbolicItem(TInt aCurrentSymbolicItem)
+ {
+ __ASSERT_ALWAYS( aCurrentSymbolicItem >=0, Panic( EEikPanicMfneIdOfSymbolicItemNotFound ) ) ;
+ TInt uninitialised = iCurrentSymbolicItem & KMfneSymbolUninitialisedBit;
+ iCurrentSymbolicItem = aCurrentSymbolicItem | uninitialised;
+ }
+
+// CEikMfneSymbol::CItem
+
+CEikMfneSymbol::CItem::CItem(TInt aId, TChar aKeyToMatch, HBufC* aText)
+ :iId(aId),
+ iKeyToMatch(aKeyToMatch),
+ iText(aText)
+ {
+ __DECLARE_NAME(_S("CItem"));
+ }
+
+EXPORT_C CEikMfneSymbol::CItem::~CItem()
+ {
+ delete iText;
+ }
+
+EXPORT_C CEikMfneSymbol::CItem* CEikMfneSymbol::CItem::NewL(TResourceReader& aResourceReader)
+ {
+ TInt id=aResourceReader.ReadInt32();
+ TChar keyToMatch=aResourceReader.ReadUint16();
+ HBufC* text=aResourceReader.ReadHBufCL();
+ CleanupStack::PushL(text);
+ CItem* symbolicItem=NewL(id, keyToMatch, text);
+ CleanupStack::Pop();
+ return symbolicItem;
+ }
+
+EXPORT_C CEikMfneSymbol::CItem* CEikMfneSymbol::CItem::NewL(TInt aId, TChar aKeyToMatch, HBufC* aText)
+ {
+ return new(ELeave) CItem(aId, aKeyToMatch, aText);
+ }
+
+EXPORT_C void CEikMfneSymbol::CItem::SetText(HBufC* aText)
+ {
+ __ASSERT_DEBUG(iText==NULL, Panic(EEikPanicMfneSymbolicItemTextHasAlreadyBeenSet));
+ iText=aText;
+ }
+
+//
+// CEikMfne
+//
+
+// Enumerations use to implement the flag setter/getter methods used with CEikMfne::iFlags
+enum TEikMfneFlagIndex
+ {
+ EConsumeUpAndDownKeysIndex = 0,
+ ESkinningBackground,
+ ESkinBackGroundControlContextSetByApi,
+ ESuppressBackgroundDrawing,
+ EUseOverrideColors
+ };
+
+EXPORT_C CEikMfne::CEikMfne()
+ :CEikBorderedControl(TGulBorder(TGulBorder::ESingleGray)),
+ iCurrentField(ENullIndex)
+ {
+ __DECLARE_NAME(_S("CEikMfne"));
+ AKNTASHOOK_ADD( this, "CEikMfne" );
+ }
+
+EXPORT_C CEikMfne::~CEikMfne()
+ {
+ AKNTASHOOK_REMOVE();
+ if (iFields)
+ {
+ if (IsFocused() && (iCurrentField!=ENullIndex) && (iFields[iCurrentField]->HighlightType()==CEikMfneField::ECursor))
+ HideCursor();
+ for (TInt i=0; i<iNumFields; ++i)
+ delete iFields[i];
+ delete [] iFields;
+ }
+ delete iExtension;
+ }
+
+EXPORT_C void CEikMfne::CreateFieldArrayL(TInt aNumFields)
+ {
+ __ASSERT_DEBUG(iFields==NULL, Panic(EEikPanicMfneFieldArrayAlreadyCreated));
+ __ASSERT_DEBUG(aNumFields>0, Panic(EEikPanicMfneTooFewFields));
+ iNumFields=aNumFields;
+ iFields=new(ELeave) CEikMfneField*[aNumFields];
+ for (TInt i=0; i<aNumFields; ++i)
+ iFields[i]=NULL;
+ // Set the flag that says background skin drawing will be done
+ EvaluateSkinningBackground();
+ CreateExtensionIfRequiredL();
+ }
+EXPORT_C void CEikMfne::ResetFieldArray()
+ {
+ if (iFields)
+ {
+ for (TInt i=0; i<iNumFields; ++i)
+ delete iFields[i];
+ delete [] iFields;
+ iFields = NULL;
+ iNumFields = 0;
+ iCurrentField = ENullIndex;
+ }
+ }
+
+EXPORT_C void CEikMfne::AddField(CEikMfneField* aField)
+ {
+ __ASSERT_DEBUG(iFields, Panic(EEikPanicMfneFieldArrayNotCreated));
+ for (TInt i=0; i<iNumFields; ++i)
+ if (iFields[i]==NULL)
+ {
+ iFields[i]=aField;
+ if ((iCurrentField==ENullIndex) && aField->IsEditable())
+ iCurrentField=i;
+ return;
+ }
+#if defined(_DEBUG)
+ Panic(EEikPanicMfneTooManyFieldsAdded);
+#endif
+ }
+
+EXPORT_C TMargins CEikMfne::BorderMargins() const
+ {
+ return iBorder.Margins();
+ }
+
+EXPORT_C TTime CEikMfne::ReadTime(TResourceReader& aResourceReader)
+ {
+ TInt second=aResourceReader.ReadUint8();
+ TInt minute=aResourceReader.ReadUint8();
+ TInt hour=aResourceReader.ReadUint8();
+ return TTime(TDateTime(0, EJanuary, 0, hour, minute, second, 0));
+ }
+
+EXPORT_C TTime CEikMfne::ReadDate(TResourceReader& aResourceReader)
+ {
+ TInt day=aResourceReader.ReadUint8();
+ TMonth month=(TMonth)aResourceReader.ReadUint8();
+ TInt year=aResourceReader.ReadInt16();
+ return TTime(TDateTime(year, month, day, 0, 0, 0, 0));
+ }
+
+EXPORT_C TTime CEikMfne::ReadTimeAndDate(TResourceReader& aResourceReader)
+ {
+ TInt second=aResourceReader.ReadUint8();
+ TInt minute=aResourceReader.ReadUint8();
+ TInt hour=aResourceReader.ReadUint8();
+ TInt day=aResourceReader.ReadUint8();
+ TMonth month=(TMonth)aResourceReader.ReadUint8();
+ TInt year=aResourceReader.ReadInt16();
+ return TTime(TDateTime(year, month, day, hour, minute, second, 0));
+ }
+
+EXPORT_C TTimeIntervalSeconds CEikMfne::ReadDuration(TResourceReader& aResourceReader)
+ {
+ TInt seconds=aResourceReader.ReadInt32();
+ __ASSERT_ALWAYS(seconds>=0, Panic(EEikPanicMfneNegativeDuration));
+ return TTimeIntervalSeconds(seconds);
+ }
+
+EXPORT_C TTimeIntervalSeconds CEikMfne::ReadTimeOffset(TResourceReader& aResourceReader)
+ {
+ TInt seconds=aResourceReader.ReadInt32();
+ return TTimeIntervalSeconds(seconds);
+ }
+
+void CEikMfne::InvalidFieldAlert()
+/**
+Display alert to user, when input is not a valid number (too big or too small etc).
+Current implementation is to play a sound alert.
+@publishedComponent
+@since 2.0
+*/
+ {
+ CAknKeySoundSystem* soundPlayer = (static_cast<CAknAppUi*>(CEikonEnv::Static()->AppUi()))->KeySounds();
+ if(soundPlayer)
+ {
+ soundPlayer->PlaySound(EAvkonSIDWarningTone);
+ }
+ }
+
+void CEikMfne::LeaveWithAlert(TInt /*aResourceId*/)
+/**
+This is to aid the old code in the derived classes which called LeaveWithInfoMsg().
+Now they leave and play warning sound to indicate a problem/correction made by the editor.
+@publishedComponent
+@since 2.0
+*/
+ {
+ InvalidFieldAlert();
+ CBaActiveScheduler::LeaveNoAlert();
+ }
+
+EXPORT_C TTimeIntervalSeconds CEikMfne::Convert(const TTime& aTime)
+ {
+ TDateTime dateTime=aTime.DateTime();
+ return TTimeIntervalSeconds(dateTime.Second()+(dateTime.Minute()*60)+(dateTime.Hour()*3600)+(dateTime.Day()*3600*24));
+ }
+
+EXPORT_C TTime CEikMfne::Convert(const TTimeIntervalSeconds& aTimeIntervalSeconds)
+ {
+ TInt timeIntervalSeconds=aTimeIntervalSeconds.Int();
+ TInt second=timeIntervalSeconds%60;
+ timeIntervalSeconds/=60;
+ TInt minute=timeIntervalSeconds%60;
+ timeIntervalSeconds/=60;
+ TInt hour=timeIntervalSeconds%24;
+ return TTime(TDateTime(0, EJanuary, 0, hour, minute, second, 0));
+ }
+
+EXPORT_C TKeyResponse CEikMfne::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
+ {
+ const TInt code=aKeyEvent.iCode;
+
+ if ( !ConsumesUpAndDownKeys() && (code==EKeyDownArrow || code==EKeyUpArrow))
+ return EKeyWasNotConsumed;
+
+ if ((aType==EEventKey) && (iCurrentField!=ENullIndex) &&
+ ( aKeyEvent.iRepeats == 0 || code == EKeyLeftArrow ||
+ code == EKeyRightArrow || code == EKeyDownArrow || code == EKeyUpArrow ) )
+ {
+ iExtension->iHighlightAll = EFalse;
+ const CFont& font=*Font();
+ CEikMfneField::THighlightType oldHighlightTypeOfOldCurrentField=iFields[iCurrentField]->HighlightType();
+ TInt oldWidthInPixelsOfOldCurrentField=iFields[iCurrentField]->WidthInPixels(font);
+ TBool dataAltered=EFalse;
+ TInt highlightIncrement=0;
+ iFields[iCurrentField]->HandleKey(font, aKeyEvent, iNumFields==1, dataAltered, highlightIncrement);
+ TInt newCurrentField;
+ for (TInt i=iCurrentField+highlightIncrement; ; i+=highlightIncrement)
+ {
+ if (i<0)
+ i=iNumFields-1;
+ else if (i>=iNumFields)
+ i=0;
+ if (iFields[i]->IsEditable())
+ {
+ newCurrentField=i;
+ break;
+ }
+ }
+ TBool error=EFalse;
+ HandleInteraction(highlightIncrement, newCurrentField, oldWidthInPixelsOfOldCurrentField, oldHighlightTypeOfOldCurrentField, dataAltered, error);
+ ReportUpdate();
+ }
+ return EKeyWasConsumed;
+ }
+
+EXPORT_C void CEikMfne::PrepareForFocusLossL()
+ {
+ if (iCurrentField!=ENullIndex)
+ {
+ TBool dataAltered=EFalse;
+ TBool error=EFalse;
+ HandleInteraction(ETrue, iCurrentField, iFields[iCurrentField]->WidthInPixels(*Font()), iFields[iCurrentField]->HighlightType(), dataAltered, error);
+ ReportUpdate();
+ }
+ }
+
+EXPORT_C TSize CEikMfne::MinimumSize()
+ {
+ return MfneSize(ETrue);
+ }
+
+EXPORT_C TCoeInputCapabilities CEikMfne::InputCapabilities() const
+ {
+#ifdef RD_SCALABLE_UI_V2
+ TCoeInputCapabilities inputCapabilities(
+ TCoeInputCapabilities::ENavigation, iExtension, NULL );
+#else
+ TCoeInputCapabilities inputCapabilities(
+ TCoeInputCapabilities::ENavigation );
+#endif // RD_SCALABLE_UI_V2
+
+ for (TInt i=0; i<iNumFields; ++i)
+ {
+ inputCapabilities.MergeWith(iFields[i]->InputCapabilities());
+ }
+
+ //inputCapabilities.SetObjectProvider(const_cast<CEikMfne*>(this));
+ if ( iExtension )
+ {
+ inputCapabilities.SetObjectProvider(
+ iExtension->iExtendedInputCapabilitiesProvider );
+ }
+
+ return inputCapabilities;
+ }
+
+EXPORT_C void CEikMfne::FocusChanged(TDrawNow aDrawNow)
+ {
+ if (iCurrentField==ENullIndex)
+ return;
+ if ( IsFocused() && iExtension && !iExtension->iDisablePenInput &&
+ iExtension->iLaunchPenInputAutomatic )
+ {
+ TRAP_IGNORE( LaunchPenInputL() );
+ }
+ if (iFields[iCurrentField]->HighlightType()==CEikMfneField::ECursor)
+ {
+ if (IsFocused())
+ DrawCursor();
+ else
+ HideCursor();
+ return;
+ }
+
+ if ( aDrawNow && !(iExtension && iExtension->iDisablePenInput) )
+ {
+ ActivateGc();
+ if ( CAknEnv::Static()->TransparencyEnabled() )
+ {
+ TRect ctrlRect = Rect();
+
+ if ( !IsBackedUp() )
+ {
+ Window().Invalidate( ctrlRect );
+ Window().BeginRedraw( ctrlRect );
+ }
+ // Just draw all, sacrifice perf a bit for vast simplicity
+ DrawRange( PreparedGc(), -1, iNumFields );
+ SystemGc().DiscardFont();
+ Window().EndRedraw();
+
+ }
+ else
+ {
+ if (iAlignment == ELayoutAlignRight || iAlignment == ELayoutAlignCenter)
+ { // need to redraw whole editor because right align
+ DrawRange( PreparedGc(), -1, iNumFields );
+ }
+ else
+ { // updating current field is enough
+ DrawRange(PreparedGc(), iCurrentField,iCurrentField);
+ }
+ SystemGc().DiscardFont();
+ }
+
+ DeactivateGc();
+ }
+ }
+
+EXPORT_C void CEikMfne::HandleInteraction(TBool aHandleDeHighlight, TInt aNewCurrentField, TInt aOldWidthInPixelsOfOldCurrentField,
+ CEikMfneField::THighlightType aOldHighlightTypeOfOldCurrentField, TBool& aDataAltered, TBool& aError)
+ {
+ const CFont& font=*Font();
+ TBool drawAllFields = ETrue;
+ if (aHandleDeHighlight)
+ {
+ iFields[iCurrentField]->HandleDeHighlight(font, *iEikonEnv, aDataAltered, aError);
+ iExtension->iValidateValueCallBack.CallBack();
+ if (aError)
+ aNewCurrentField=iCurrentField;
+ else
+ FieldIsAboutToBeDeHighlighted(iFields[iCurrentField], drawAllFields);
+ }
+ TInt oldCurrentField=iCurrentField;
+ iCurrentField=aNewCurrentField;
+
+ if ( aDataAltered )
+ {
+ ReportEventL(MCoeControlObserver::EEventStateChanged);
+ }
+
+ CEikMfneField::THighlightType newHighlightTypeOfOldCurrentField=iFields[oldCurrentField]->HighlightType();
+ CEikMfneField::THighlightType highlightTypeOfCurrentField=iFields[iCurrentField]->HighlightType();
+
+ ActivateGc();
+ if ( CAknEnv::Static()->TransparencyEnabled() )
+ {
+ if ( !IsBackedUp() )
+ {
+ TRect ctrlRect = Rect();
+ Window().Invalidate( ctrlRect );
+ Window().BeginRedraw( ctrlRect );
+ }
+
+ // Just draw all, sacrifice perf a bit for vast simplicity
+ drawAllFields = ETrue;
+ }
+
+ SystemGc().Reset();
+ CWindowGc& gc=PreparedGc();
+
+ if (drawAllFields ||iAlignment == ELayoutAlignRight || iAlignment == ELayoutAlignCenter) // draw all fields in case of right align
+ DrawRange(gc, -1, iNumFields);
+ else
+ {
+ TInt newWidthInPixelsOfOldCurrentField=iFields[oldCurrentField]->WidthInPixels(font);
+ TInt firstFieldToDraw=(aDataAltered ||
+ ((iCurrentField!=oldCurrentField) && (aOldHighlightTypeOfOldCurrentField==CEikMfneField::EInverseVideo)) ||
+ ((iCurrentField==oldCurrentField) && (aOldHighlightTypeOfOldCurrentField!=newHighlightTypeOfOldCurrentField)))?
+ oldCurrentField: oldCurrentField+1;
+ TInt lastFieldToDraw=(newWidthInPixelsOfOldCurrentField!=aOldWidthInPixelsOfOldCurrentField)? iNumFields: oldCurrentField;
+ DrawRange(gc, firstFieldToDraw, lastFieldToDraw);
+ if ((iCurrentField!=oldCurrentField) && ((iCurrentField<firstFieldToDraw) || (iCurrentField>lastFieldToDraw)))
+ {
+ __ASSERT_DEBUG(highlightTypeOfCurrentField==CEikMfneField::EInverseVideo, Panic(EEikPanicMfneInverseVideoHighlightTypeExpected));
+ DrawRange(gc, iCurrentField, iCurrentField);
+ }
+ }
+ if ( (aOldHighlightTypeOfOldCurrentField==CEikMfneField::ECursor) &&
+ ((iCurrentField!=oldCurrentField) ||
+ (newHighlightTypeOfOldCurrentField!=CEikMfneField::ECursor)))
+ {
+ __ASSERT_DEBUG(highlightTypeOfCurrentField!=CEikMfneField::ECursor, Panic(EEikPanicMfneBadCursorState1));
+ HideCursor();
+ }
+ if ( (highlightTypeOfCurrentField==CEikMfneField::ECursor) &&
+ ((aOldHighlightTypeOfOldCurrentField!=CEikMfneField::ECursor) || aDataAltered))
+ {
+ __ASSERT_DEBUG(iCurrentField==oldCurrentField, Panic(EEikPanicMfneBadCursorState2));
+ DrawCursor();
+ }
+ gc.DiscardFont();
+ if ( CAknEnv::Static()->TransparencyEnabled() && !IsBackedUp() )
+ {
+ Window().EndRedraw();
+ }
+ DeactivateGc();
+ }
+
+EXPORT_C void CEikMfne::FieldIsAboutToBeDeHighlighted(CEikMfneField*, TBool&)
+ {
+ }
+
+EXPORT_C void CEikMfne::DrawNowAndLeaveWithTimeDateFormatInfoMsgL(TInt /*aResourceId*/, const TTime& /*aTimeDate*/) const
+ {
+ CEikMfne::InvalidFieldAlert();
+ DrawNow();
+// AVKON does not show info messages, removed because they take up lots of time and space
+ CBaActiveScheduler::LeaveNoAlert();
+ }
+
+EXPORT_C CEikMfneField* CEikMfne::Field(TInt aField) const
+ {
+ return (aField<0 || aField>=iNumFields)?NULL:iFields[aField];
+ }
+
+EXPORT_C void CEikMfne::SetMfneAlignment(TInt aAlignment)
+ {
+ if( !iExtension )
+ {
+ TRAPD( err, CreateExtensionIfRequiredL() );
+ if ( err != KErrNone )
+ {
+ return;
+ }
+ }
+ if ( aAlignment >= ELayoutAlignNone && iExtension )
+ {
+ iAlignment = aAlignment;
+ TUint capabilities = iExtension->
+ iExtendedInputCapabilities->Capabilities();
+ capabilities &=
+ ~( CAknExtendedInputCapabilities::KAknEditorAlignMask );
+ switch( iAlignment )
+ {
+ case ELayoutAlignCenter:
+ capabilities |=
+ CAknExtendedInputCapabilities::EInputEditorAlignCenter;
+ break;
+ case ELayoutAlignLeft:
+ capabilities |=
+ CAknExtendedInputCapabilities::EInputEditorAlignLeft;
+ break;
+ case ELayoutAlignRight:
+ capabilities |=
+ CAknExtendedInputCapabilities::EInputEditorAlignRight;
+ break;
+ case ELayoutAlignBidi:
+ capabilities |=
+ CAknExtendedInputCapabilities::EInputEditorAlignBidi;
+ break;
+ default:
+ break;
+ }
+ iExtension->iExtendedInputCapabilities->SetCapabilities(
+ capabilities );
+ }
+
+ MfneSize();
+ }
+
+EXPORT_C void CEikMfne::SetUpAndDownKeysConsumed(TBool aConsume)
+ {
+ iFlags.Assign( EConsumeUpAndDownKeysIndex, aConsume );
+ }
+
+EXPORT_C void CEikMfne::SetSuppressBackgroundDrawing( TBool aSuppress )
+ {
+ iFlags.Assign( ESuppressBackgroundDrawing, aSuppress );
+ }
+
+EXPORT_C TInt CEikMfne::SetFeature( TInt aFeatureId, TInt aFeatureParam )
+ {
+ TInt ret = KErrNone;
+
+ if ( !SupportsFeature( aFeatureId ) )
+ {
+ ret = KErrNotSupported;
+ }
+ else
+ {
+ switch ( aFeatureId )
+ {
+ case EClipGcToRect:
+ if ( iExtension )
+ {
+ iExtension->iClipGcToRect = aFeatureParam;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+
+ case EDisablePenInput:
+ if ( iExtension )
+ {
+ iExtension->iDisablePenInput = aFeatureParam;
+ iExtension->iFingerSupport = !( iExtension->iDisablePenInput != 0 );
+ iExtension->iHighlightAll = EFalse;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ case EFingerSupport:
+ if ( iExtension )
+ {
+ iExtension->iFingerSupport = ( TBool )( aFeatureParam );
+ iExtension->iDisablePenInput = !( iExtension->iFingerSupport );
+ iExtension->iFingerParam = aFeatureParam;
+ iExtension->iHighlightAll = ( iExtension->iFingerSupport &&
+ aFeatureParam == EnableWithAllHighlight );
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ case ELaunchPenInputAutomatic:
+ if ( iExtension )
+ {
+ iExtension->iLaunchPenInputAutomatic = aFeatureParam;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ case EPartialScreenInput:
+ if ( iExtension )
+ {
+ iExtension->iPartialScreenInput = aFeatureParam;
+ TUint caps( iExtension->iExtendedInputCapabilities->Capabilities() );
+ if ( aFeatureParam )
+ {
+ caps |= CAknExtendedInputCapabilities::EInputEditorPartialScreen;
+ }
+ else
+ {
+ caps &= ~CAknExtendedInputCapabilities::EInputEditorPartialScreen;
+ }
+ iExtension->iExtendedInputCapabilities->SetCapabilities( caps );
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ default:
+ ret = KErrNotSupported;
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+EXPORT_C TInt CEikMfne::GetFeature( TInt aFeatureId, TInt& aFeatureParam ) const
+ {
+ TInt ret = KErrNone;
+
+ if ( !SupportsFeature( aFeatureId ) )
+ {
+ ret = KErrNotSupported;
+ }
+ else
+ {
+ switch ( aFeatureId )
+ {
+ case EClipGcToRect:
+ if ( iExtension )
+ {
+ aFeatureParam = iExtension->iClipGcToRect;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+
+ case EDisablePenInput:
+ if ( iExtension )
+ {
+ aFeatureParam = iExtension->iDisablePenInput;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ case EFingerSupport:
+ if ( iExtension )
+ {
+ aFeatureParam = iExtension->iFingerParam;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ case ELaunchPenInputAutomatic:
+ if ( iExtension )
+ {
+ aFeatureParam = iExtension->iLaunchPenInputAutomatic;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ case EPartialScreenInput:
+ if ( iExtension )
+ {
+ aFeatureParam = iExtension->iPartialScreenInput;
+ }
+ else
+ {
+ ret = KErrGeneral;
+ }
+ break;
+ default:
+ ret = KErrNotSupported;
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+EXPORT_C TBool CEikMfne::SupportsFeature( TInt aFeatureId ) const
+ {
+ // This is done so that there is an option of leaving out
+ // a feature instead of using the enum TFeatureId, although
+ // for simplified BC that will probably never be done.
+ const TInt supportedFeatures[] =
+ {
+ EClipGcToRect,
+ EDisablePenInput,
+ EFingerSupport,
+ ELaunchPenInputAutomatic,
+ EPartialScreenInput
+ };
+
+ TBool ret = EFalse;
+
+ for ( TInt i = 0; i < sizeof( supportedFeatures ) / sizeof( TInt ); ++i )
+ {
+ if ( supportedFeatures[i] == aFeatureId )
+ {
+ ret = ETrue;
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+void CEikMfne::HighlightField( TInt aFieldPosition )
+ {
+ TBool dataAltered = ETrue;
+ TBool error = EFalse;
+ const CFont& font=*Font();
+ HandleInteraction(ETrue, aFieldPosition, iFields[iCurrentField]->WidthInPixels(font), iFields[iCurrentField]->HighlightType(), dataAltered, error);
+ }
+
+EXPORT_C const CFont* CEikMfne::Font() const
+ {
+ if (iFont)
+ {
+ return iFont;
+ }
+ else
+ {
+ return AknLayoutUtils::FontFromId( EAknLogicalFontPrimaryFont );
+ }
+ }
+
+EXPORT_C void CEikMfne::SetFont(const CFont* aFont)
+ {
+ TBool fontChanged(iFont==aFont);
+ iFont = aFont;
+ if (fontChanged)
+ MfneSize();
+ }
+
+EXPORT_C void CEikMfne::SetSkinBackgroundControlContextL( MAknsControlContext* aControlContext )
+ {
+ CreateExtensionIfRequiredL();
+ if ( iExtension )
+ {
+ iExtension->iExternalSkinControlContext = aControlContext;
+ iFlags.Set(ESkinBackGroundControlContextSetByApi);
+ }
+ }
+
+EXPORT_C TSize CEikMfne::MfneSize() const
+ {
+ return ((CEikMfne*)this)->MfneSize(EFalse); // cast away the const-ness
+ }
+
+EXPORT_C TSize CEikMfne::MfneSize(TBool aShrinkToMinimumSize)
+ {
+ const CFont& font=*Font();
+ TSize size=iBorder.SizeDelta(); // Shrink to border first
+
+ size.iHeight=Rect().Height(); // Do not change height
+ iBorder.SizeDelta(); // Shrink to border first
+
+ TInt leftHighlightExtension;
+ TInt rightHighlightExtension;
+ TAknTextDecorationMetrics decoration( &font );
+ decoration.GetLeftAndRightMargins( leftHighlightExtension, rightHighlightExtension);
+
+ size.iWidth += leftHighlightExtension + rightHighlightExtension;
+
+ if( iFields )
+ {
+ for (TInt i=0; i<iNumFields; ++i)
+ size.iWidth+=iFields[i]->MaximumWidthInPixels(font, aShrinkToMinimumSize);
+ }
+
+ TRect rect = Rect();
+ switch ( iAlignment )
+ {
+ case ELayoutAlignCenter:
+ {
+ TInt fieldXPosition = rect.iTl.iX + (rect.Width() - size.iWidth) / 2;
+ SetExtent(TPoint(fieldXPosition, rect.iTl.iY), TSize(size));
+ }
+ break;
+ case ELayoutAlignRight:
+ {
+ TInt fieldXPosition = rect.iTl.iX + (rect.Width() - size.iWidth);
+ SetExtent(TPoint(fieldXPosition, rect.iTl.iY), TSize(size));
+ }
+ break;
+ case ELayoutAlignLeft: // Left alignment is default
+ case ELayoutAlignBidi: // Bidi should be ignored, so it's the same as default
+ default:
+ {
+ iSize=size;
+ }
+ break;
+ }
+
+ return iSize;
+ }
+
+EXPORT_C void CEikMfne::Draw(const TRect& /*aRect*/) const
+ {
+ CWindowGc& gc=PreparedGc();
+ TRect rect=Rect();
+
+ // Inhibit border if skinning
+ if ( !SkinningBackground() )
+ iBorder.Draw(gc, rect);
+
+ DrawRange( gc, -1, iNumFields, ETrue );
+ gc.DiscardFont(); // this is not nice if there are eg. child controls to draw..
+
+ }
+
+EXPORT_C void* CEikMfne::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikMfne::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CCoeControl::HandlePointerEventL(aPointerEvent);
+
+ if ((aPointerEvent.iType==TPointerEvent::EButton1Down) || (aPointerEvent.iType==TPointerEvent::EDrag))
+ {
+ const CFont& font=*Font();
+ TInt newField=ENullIndex;
+ TMargins borderMargins=iBorder.Margins();
+
+ TInt leftHighlightExtension;
+ TInt rightHighlightExtension;
+ TAknTextDecorationMetrics decoration( &font );
+ decoration.GetLeftAndRightMargins( leftHighlightExtension, rightHighlightExtension );
+
+ TInt leftPositionOfThisField =
+ iPosition.iX + borderMargins.iLeft + EGapLeftOfFirstField + leftHighlightExtension;
+
+ // No need to do anything in the block below in case of left align
+ if ( iAlignment == ELayoutAlignCenter ||
+ iAlignment == ELayoutAlignRight )
+ {
+ TInt mfneWidth( 0 );
+ for ( TInt i=0; i < iNumFields; ++i )
+ {
+ mfneWidth += iFields[i]->WidthInPixels( font );
+ }
+
+ if ( iAlignment == ELayoutAlignCenter )
+ {
+ leftPositionOfThisField += ( iSize.iWidth - mfneWidth ) / 2;
+ }
+ else if ( iAlignment == ELayoutAlignRight )
+ {
+ leftPositionOfThisField += ( iSize.iWidth - mfneWidth );
+ }
+ }
+
+ // TInt leftPositionOfNewField=0; // dummy initialization to prevent compiler warning (NOT USED)
+ TInt rightPositionOfNewField=0; // dummy initialization to prevent compiler warning
+ for (TInt i=0; i<iNumFields; ++i)
+ {
+ TInt widthOfThisFieldInPixels=iFields[i]->WidthInPixels(font);
+ if (iFields[i]->IsEditable())
+ {
+ TInt rightPositionOfThisField=(leftPositionOfThisField+widthOfThisFieldInPixels)-1;
+ if (rightPositionOfThisField<aPointerEvent.iPosition.iX)
+ {
+ newField=i;
+ //leftPositionOfNewField=leftPositionOfThisField;
+ rightPositionOfNewField=rightPositionOfThisField;
+ }
+ else
+ {
+ if ((newField==ENullIndex) || (leftPositionOfThisField-aPointerEvent.iPosition.iX<aPointerEvent.iPosition.iX-rightPositionOfNewField))
+ {
+ newField=i;
+ // leftPositionOfNewField and rightPositionOfNewField do not need to be set as they are not going to be used again
+ }
+ break;
+ }
+ }
+ leftPositionOfThisField+=widthOfThisFieldInPixels;
+ }
+ if (newField==ENullIndex)
+ newField=iCurrentField;
+
+ if (iExtension && aPointerEvent.iType == TPointerEvent::EButton1Down)
+ {
+ // Edit feedback on down event in current field,
+ // Edit feedback when changing fields
+ TTouchLogicalFeedback feedback = ETouchFeedbackEdit;
+ iExtension->iFeedback->InstantFeedback( this, feedback );
+ }
+ TBool createPopoutIfRequired=((newField==iCurrentField) && aPointerEvent.iType==TPointerEvent::EButton1Down && IsFocused());
+ TBool dataAltered=EFalse;
+ TBool error=EFalse;
+ HandleInteraction(ETrue, newField, iFields[iCurrentField]->WidthInPixels(font), iFields[iCurrentField]->HighlightType(), dataAltered, error);
+ if (createPopoutIfRequired)
+ CreatePopoutIfRequiredL();
+
+ ReportEventL( MCoeControlObserver::EEventStateChanged );
+ ReportUpdate();
+ }
+ else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+ {
+ if ( iExtension && !iExtension->iDisablePenInput )
+ {
+ iExtension->iFeedback->InstantFeedback( this,
+ ETouchFeedbackEdit,
+ ETouchFeedbackVibra,
+ aPointerEvent );
+ LaunchPenInputL();
+ }
+ }
+ }
+
+EXPORT_C TTypeUid::Ptr CEikMfne::MopSupplyObject( TTypeUid aId )
+ {
+ if ( aId.iUid == CAknExtendedInputCapabilities::ETypeId && iExtension )
+ {
+ return aId.MakePtr( iExtension->iExtendedInputCapabilities );
+ }
+
+ return CCoeControl::MopSupplyObject( aId );
+ }
+
+EXPORT_C void CEikMfne::CreatePopoutIfRequiredL()
+ {
+ // does nothing
+ }
+
+// ----------------------------------------------------------------------------
+// Draws the specified range of fields.
+// ----------------------------------------------------------------------------
+//
+void CEikMfne::DrawRange( CWindowGc& aGc,
+ TInt aFirstField,
+ TInt aLastField,
+ TBool aSkipBackgroundDrawer ) const
+ {
+ const MCoeControlBackground* backgroundDrawer = FindBackground();
+
+ TInt leftHighlightExtension;
+ TInt rightHighlightExtension;
+
+ TInt topHighlightExtension;
+ TInt bottomHighlightExtension;
+ TAknTextDecorationMetrics decoration( Font() );
+ decoration.GetTopAndBottomMargins( topHighlightExtension, bottomHighlightExtension);
+ decoration.GetLeftAndRightMargins( leftHighlightExtension, rightHighlightExtension);
+
+ // Some values that will be needed for Skins. These will behave when not skinned, etc..
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ MAknsControlContext* edCc = SkinBackgroundControlContext();
+
+ TInt skinDrawFlags = KAknsDrawParamDefault;
+ if ( CAknEnv::Static()->TransparencyEnabled() )
+ {
+ skinDrawFlags = KAknsDrawParamNoClearUnderImage;
+ }
+
+ // N.B. a value of iNumFields for aFirstField or aLastField is permitted, this means draw the space after the last field, and similarly
+ // a value of -1 is permitted which means draw the space before the first field
+ __ASSERT_DEBUG((aFirstField>=-1) && (aFirstField<=iNumFields) && (aLastField>=-1) && (aLastField<=iNumFields), Panic(EEikPanicMfneBadRangeToDraw));
+ // N.B. aLastField is permitted to be less than aFirstField, in which case nothing will be drawn
+ if (aFirstField<=aLastField)
+ {
+ TBool drawtrailingSpace=EFalse;
+ if (aLastField==iNumFields)
+ {
+ if (iAlignment != ELayoutAlignRight)
+ drawtrailingSpace=ETrue;
+ --aLastField;
+ }
+ TMargins borderMargins=iBorder.Margins();
+
+ TInt alignLeftOffset = VerticalOffsetForMfnePosition();
+ const CFont& font=*Font();
+
+ TBool clipGcToRect( EFalse );
+
+ if ( iExtension )
+ {
+ clipGcToRect = iExtension->iClipGcToRect;
+ }
+
+ if (iAlignment == ELayoutAlignRight)
+ {
+ alignLeftOffset = iSize.iWidth-VerticalOffsetForMfnePosition();
+ for (TInt i = 0; i <= aLastField;i++ )
+ alignLeftOffset -= iFields[i]->WidthInPixels(font);
+
+ if (alignLeftOffset < 0 && !clipGcToRect )
+ alignLeftOffset = 0; // fields are not goin to fit anyway.
+ }
+ if (iAlignment == ELayoutAlignCenter)
+ {
+ alignLeftOffset = iSize.iWidth-VerticalOffsetForMfnePosition();
+ for (TInt i = 0; i <= aLastField;i++ )
+ alignLeftOffset -= iFields[i]->WidthInPixels(font);
+
+ if (alignLeftOffset < 0 && !clipGcToRect )
+ alignLeftOffset = 0; // fields are not goin to fit anyway.
+ alignLeftOffset /= 2;
+ }
+
+ const TPoint topLeftOfMfne(iPosition.iX+borderMargins.iLeft, iPosition.iY+borderMargins.iTop);
+ TPoint topLeftOfField(topLeftOfMfne);
+ topLeftOfField.iX += alignLeftOffset;
+
+ TInt posX = topLeftOfField.iX;
+ TRect controlRect = Rect();
+ posX += leftHighlightExtension;
+ for (TInt i = 0; i <= aLastField;i++ )
+ {
+ posX += iFields[i]->WidthInPixels(font);
+ }
+ if (posX < controlRect.iBr.iX )
+ {
+ topLeftOfField.iX+= leftHighlightExtension;
+ }
+
+ TInt textHeight=font.HeightInPixels();
+
+ if (aFirstField==-1)
+ {
+ SetGcToNormalVideo(aGc);
+ // Clear the area between the mfne left border and the first field of the mfne
+ TRect clearRect( topLeftOfMfne, TSize( (topLeftOfField.iX - topLeftOfMfne.iX), Rect().Height() ) );
+
+ TBool skinnedDraw = EFalse;
+
+ if ( !iFlags[ESuppressBackgroundDrawing] )
+ {
+ if ( backgroundDrawer )
+ {
+ if ( !aSkipBackgroundDrawer )
+ {
+ backgroundDrawer->Draw( aGc, *this, clearRect );
+ }
+
+ skinnedDraw = ETrue;
+ }
+ else if ( SkinningBackground() && !iFlags[EUseOverrideColors] )
+ {
+ skinnedDraw = AknsDrawUtils::Background(
+ skin, edCc, this, aGc, clearRect, skinDrawFlags );
+ }
+ if ( !skinnedDraw ) // legacy code ( rect construction move to above)
+ {
+ aGc.Clear( clearRect );
+ }
+ }
+
+ ++aFirstField;
+ }
+ //if there is one field with text, whole MFNE editor should
+ //be highlighted when highlight all feature is enabled.
+ TBool isEmpty( ETrue );
+ for ( TInt i( 0 ); i< aLastField; i++ )
+ {
+ if ( iFields[i]->FieldText().Length() > 0 )
+ {
+ isEmpty = EFalse;
+ break;
+ }
+ }
+ TBool focused = IsFocused();
+ for (TInt i=0; i<=aLastField; ++i)
+ {
+ if (i>=aFirstField)
+ {
+ if (focused && ( iExtension->iHighlightAll || ( i == iCurrentField
+ && iFields[i]->HighlightType() == CEikMfneField::EInverseVideo
+ && iFields[i]->FieldText().Length() > 0 ) ) && !isEmpty )
+ {
+ // Currently no skin effect for the highlighted field drawing
+ SetGcToInverseVideo(aGc);
+ }
+ else
+ {
+ if (IsDimmed())
+ SetGcToDimmedVideo(aGc);
+ else
+ SetGcToNormalVideo(aGc);
+
+ // Note!! This is taking responsibility away from the CEikMfne Field for drawing
+ // Skin background is drawn for the fields here
+ if( SkinningBackground() && !iFlags[EUseOverrideColors] )
+ {
+ // Note that in case EUseOverrideColors is up, there is no need
+ // to clear here, as the ENullBrush below is skipped and therefore
+ // the field will draw its own background with the overridden color
+ if ( !iFlags[ESuppressBackgroundDrawing] )
+ {
+ TRect clearRect(
+ TPoint( topLeftOfField.iX, topLeftOfMfne.iY ),
+ TPoint(
+ topLeftOfField.iX +(iFields[i]->WidthInPixels(font)),
+ topLeftOfMfne.iY + Rect().Height()
+ ) );
+
+ if ( backgroundDrawer )
+ {
+ if ( !aSkipBackgroundDrawer )
+ {
+ backgroundDrawer->Draw( aGc, *this, clearRect );
+ }
+ }
+ else
+ {
+ AknsDrawUtils::Background(
+ skin, edCc, this, aGc, clearRect, skinDrawFlags );
+ }
+ }
+
+ // Set up null brush GC here for the upcoming draw
+ aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
+ }
+ }
+ // This draw must only draw the text with a null brush or draw block highlight
+ iFields[i]->Draw(aGc, font, topLeftOfField);
+ }
+ topLeftOfField.iX+=iFields[i]->WidthInPixels(font); // Increment field Position
+ }
+ if (drawtrailingSpace)
+ {
+ SetGcToNormalVideo(aGc);
+ if ( !iFlags[ESuppressBackgroundDrawing] )
+ {
+ TInt width=0;
+ if (iAlignment == ELayoutAlignCenter)
+ {
+ width = iSize.iWidth-VerticalOffsetForMfnePosition();
+ for(TInt i=0;i<iNumFields;i++)
+ width -= iFields[i]->WidthInPixels(font);
+ if (width < 0) width = 0;
+ width /= 2;
+ }
+
+ TRect clearRect;
+ if ( CAknEnv::Static()->TransparencyEnabled() )
+ {
+ clearRect = TRect( topLeftOfField,
+ TPoint( iPosition.iX + iSize.iWidth, topLeftOfMfne.iY+Rect().Height() ));
+ }
+ else
+ {
+ clearRect = TRect( topLeftOfField,
+ TPoint(iPosition.iX + width + iSize.iWidth, topLeftOfMfne.iY+Rect().Height() ));
+ }
+
+ TBool skinnedDraw = EFalse;
+
+ if ( backgroundDrawer )
+ {
+ if ( !aSkipBackgroundDrawer )
+ {
+ backgroundDrawer->Draw( aGc, *this, clearRect );
+ }
+
+ skinnedDraw = ETrue;
+ }
+ else if ( SkinningBackground() && !iFlags[EUseOverrideColors] )
+ {
+ skinnedDraw = AknsDrawUtils::Background(
+ skin, edCc, this, aGc, clearRect, skinDrawFlags );
+ }
+ if ( !skinnedDraw )
+ {
+ aGc.Clear( clearRect );
+ }
+ }
+ }
+ }
+ }
+
+CWindowGc& CEikMfne::PreparedGc() const
+ {
+ CWindowGc& gc=SystemGc();
+ gc.SetBrushStyle(CWindowGc::ESolidBrush);
+ gc.UseFont(Font()); // The font must be discarded also -> always when using PreparedGc(),
+
+ if ( iExtension && iExtension->iClipGcToRect )
+ {
+ gc.SetClippingRect( Rect() );
+ }
+
+ return gc; // and finishing drawing, gc.DiscardFont must be called
+ }
+
+void CEikMfne::SetGcToNormalVideo(CWindowGc& aGc) const
+ {
+ TRgb textColor = AKN_LAF_COLOR(215);
+ TRgb bgColor = iEikonEnv->ControlColor(EColorControlBackground,*this);
+
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+ if ( iFlags[EUseOverrideColors] )
+ {
+ textColor = iEikonEnv->ControlColor( EColorControlText, *this );
+ }
+ else if ( skin && iExtension )
+ {
+ AknsUtils::GetCachedColor(skin, textColor, KAknsIIDQsnTextColors, iExtension->iAknSkinColorIndex);
+ AknsUtils::GetCachedColor(skin, bgColor, KAknsIIDQsnTextColors, iExtension->iSkinIdForTextBackgroundColor);
+ }
+
+ aGc.SetPenColor(textColor); // Text color
+ aGc.SetBrushColor(bgColor);
+ }
+
+void CEikMfne::SetGcToInverseVideo(CWindowGc& aGc) const
+ {
+ TRgb hightext = AKN_LAF_COLOR(0); // Hightlighted text color // AVKON LAF
+ TRgb highcolor = AKN_LAF_COLOR(210); // Highlight color // AVKON LAF
+
+ if ( iFlags[EUseOverrideColors] )
+ {
+ hightext = iEikonEnv->ControlColor( EColorControlHighlightText, *this );
+ highcolor = iEikonEnv->ControlColor( EColorControlHighlightBackground, *this );
+ }
+ else
+ {
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ AknsUtils::GetCachedColor(skin, hightext, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG24);
+ AknsUtils::GetCachedColor(skin, highcolor, KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG2);
+ }
+
+ aGc.SetPenColor(hightext);
+ aGc.SetBrushColor(highcolor);
+
+ // Ensure highlight in inverse video
+ aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+ }
+
+void CEikMfne::SetGcToDimmedVideo(CWindowGc& aGc) const
+ {
+ if ( iFlags[EUseOverrideColors] )
+ {
+ aGc.SetPenColor(iEikonEnv->ControlColor(EColorControlDimmedText,*this)); //KEikMfneDimmedColor);
+ aGc.SetBrushColor(iEikonEnv->ControlColor(EColorControlBackground,*this)); //KEikMfneBackgroundColor);
+ }
+ else
+ {
+ SetGcToNormalVideo(aGc);
+ }
+ }
+
+void CEikMfne::GetCursorInfo( TPoint& aPos, TInt& aHeight, TInt& aWidth,
+ TInt& aAscent )
+ {
+ const CFont& font=*Font();
+ const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( &font );
+ if ( layoutFont )
+ {
+ TInt topMargin;
+ TInt bottomMargin;
+ TAknTextDecorationMetrics metrics = layoutFont->TextDecorationMetrics();
+ metrics.GetTopAndBottomMargins( topMargin, bottomMargin );
+ aHeight = layoutFont->TextPaneHeight() + topMargin + bottomMargin;
+ aWidth = metrics.CursorWidth();
+ aAscent = layoutFont->TextPaneHeight();
+ // The ascent is according to CursorAscentFromFont. It doesn't really make a
+ // difference because it is added to the cursor TPoint and then used again
+ // in CEikonEnv::DrawCursor
+ }
+ else
+ { // The old way
+ aHeight = AknLayoutUtils::CursorHeightFromFont( font.FontSpecInTwips() );
+ aWidth = AknLayoutUtils::CursorWidthFromFont ( font.FontSpecInTwips() );
+ aAscent = AknLayoutUtils::CursorAscentFromFont( font.FontSpecInTwips() );
+ }
+
+ TMargins borderMargins = iBorder.Margins();
+ aPos.iX = iPosition.iX + borderMargins.iLeft + EGapLeftOfFirstField;
+ aPos.iY = iPosition.iY + borderMargins.iTop + EGapAboveText +
+ aAscent + ( EMfneFieldExtraHeight / 2 );
+
+ if ( iAlignment == ELayoutAlignRight )
+ {
+ aPos.iX = iPosition.iX + iSize.iWidth - VerticalOffsetForMfnePosition();
+ for ( TInt i = iNumFields-1 ; i >= iCurrentField ; i-- )
+ {
+ aPos.iX -= iFields[i]->WidthInPixels(font);
+ }
+ }
+ else if (iAlignment == ELayoutAlignCenter)
+ {
+ TInt width = iSize.iWidth-VerticalOffsetForMfnePosition();
+ for ( TInt i = 0; i < iNumFields; i++ )
+ {
+ width -= iFields[i]->WidthInPixels( font );
+ }
+ if ( width < 0 )
+ {
+ width = 0;
+ }
+ width /= 2;
+ aPos.iX += width;
+ for (TInt i = 0; i<iCurrentField; ++i)
+ {
+ aPos.iX += iFields[i]->WidthInPixels( font );
+ }
+ }
+ else
+ {
+ for ( TInt i = 0; i < iCurrentField; ++i )
+ {
+ aPos.iX += iFields[i]->WidthInPixels( font );
+ }
+ }
+
+ aPos.iX += iFields[iCurrentField]->
+ DistanceFromStartOfFieldToEndOfTextInPixels( font );
+ }
+
+void CEikMfne::DrawCursor()
+ {
+ __ASSERT_DEBUG(IsFocused() && (iFields[iCurrentField]->HighlightType()==CEikMfneField::ECursor), Panic(EEikPanicMfneBadCursorState3));
+
+ TInt cursorHeight( 0 );
+ TInt cursorWidth( 0 );
+ TInt cursorAscent( 0 );
+ TPoint cursorPosition( 0, 0 );
+
+ GetCursorInfo( cursorPosition, cursorHeight, cursorWidth, cursorAscent );
+
+ iEikonEnv->DrawCursor(this, cursorPosition, cursorWidth, cursorAscent, cursorHeight);
+ iExtension->iCursorShown = ETrue;
+ }
+
+void CEikMfne::HideCursor()
+ {
+ if ( iExtension->iCursorShown )
+ {
+ iEikonEnv->HideCursor(this);
+ iExtension->iCursorShown = EFalse;
+ }
+ }
+
+
+void CEikMfne::ReportUpdate()
+ {
+ if ( iExtension )
+ {
+ TRAP_IGNORE (
+ iExtension->iExtendedInputCapabilities->ReportEventL(
+ CAknExtendedInputCapabilities::MAknEventObserver::EControlContentUpdatedInternally,
+ NULL );
+ )
+ }
+ }
+
+/**
+ * Gets the list of logical colors employed in the drawing of the control,
+ * paired with an explanation of how they are used. Appends the list to aColorUseList.
+ *
+ * @since ER5U
+ */
+EXPORT_C void CEikMfne::GetColorUseListL(CArrayFix<TCoeColorUse>& aColorUseList) const
+ {
+ CEikBorderedControl::GetColorUseListL(aColorUseList);
+
+ TInt commonAttributes = TCoeColorUse::EContents|TCoeColorUse::ENormal|TCoeColorUse::ENeutral;
+ TCoeColorUse colorUse;
+
+ colorUse.SetLogicalColor(EColorControlText);
+ colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EActive|commonAttributes);
+ aColorUseList.AppendL(colorUse);
+
+ colorUse.SetLogicalColor(EColorControlHighlightText);
+ colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EHighlights|commonAttributes);
+ aColorUseList.AppendL(colorUse);
+
+ colorUse.SetLogicalColor(EColorControlDimmedText);
+ colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EDimmed|commonAttributes);
+ aColorUseList.AppendL(colorUse);
+
+ colorUse.SetLogicalColor(EColorControlBackground);
+ colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EActive|commonAttributes);
+ aColorUseList.AppendL(colorUse);
+
+ colorUse.SetLogicalColor(EColorControlHighlightBackground);
+ colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EHighlights|commonAttributes);
+ aColorUseList.AppendL(colorUse);
+ }
+
+/**
+ * Handles a change to the control's resources of type aType
+ * which are shared across the environment, e.g. colors or fonts.
+ *
+ * @since ER5U
+ */
+EXPORT_C void CEikMfne::HandleResourceChange(TInt aType)
+ {
+ EvaluateSkinningBackground();
+ CEikBorderedControl::HandleResourceChange(aType);
+ if ( aType == KEikDynamicLayoutVariantSwitch && iFields )
+ {
+ if ( IsFocused() && iFields[iCurrentField]->HighlightType() ==
+ CEikMfneField::ECursor )
+ {
+ HideCursor();
+ DrawCursor();
+ }
+ }
+ }
+
+/**
+ * Writes the internal state of the control and its components to aStream.
+ * Does nothing in release mode.
+ * Designed to be overidden and base called by subclasses.
+ *
+ * @internal
+ * @since App-Framework_6.1
+ */
+#ifndef _DEBUG
+EXPORT_C void CEikMfne::WriteInternalStateL(RWriteStream&) const
+ {}
+#else
+EXPORT_C void CEikMfne::WriteInternalStateL(RWriteStream& aWriteStream) const
+ {
+ CEikBorderedControl::WriteInternalStateL(aWriteStream);
+ }
+#endif
+
+EXPORT_C void CEikMfne::Reserved_2()
+ {
+ }
+
+EXPORT_C void CEikMfne::CEikMfne_Reserved()
+ {
+ }
+
+
+// -----------------------------------------------------------------------------
+// CEikMfne::HandleMfneCommandL
+// Handles external MFNE commands
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CEikMfne::HandleMfneCommandL(TInt aCommand)
+ {
+ if( !AknLayoutUtils::PenEnabled() )
+ {
+ return;
+ }
+
+ // store the original setting
+ TBool original = ConsumesUpAndDownKeys();
+
+ if(!original)
+ {
+ // We need to enable the up/down key support to simulate key events
+ SetUpAndDownKeysConsumed(ETrue);
+ }
+
+ TKeyEvent event;
+ event.iCode = 0;
+ event.iScanCode = 0;
+ event.iModifiers = 0;
+ event.iRepeats = 0;
+
+ switch(aCommand)
+ {
+ case MAknMfneCommandObserver::EMfneIncrementCurrentFieldValue:
+ // Increment current field value by simulating internally
+ // an up arrow key event
+ event.iCode = EKeyUpArrow;
+ OfferKeyEventL(event, EEventKey);
+ break;
+
+ case MAknMfneCommandObserver::EMfneDecrementCurrentFieldValue:
+ // Decrement current field value by simulating internally
+ // a down arrow key event
+ event.iCode = EKeyDownArrow;
+ OfferKeyEventL(event, EEventKey);
+ break;
+
+ default:
+ break;
+ }
+
+ if(!original)
+ {
+ // restore the original setting
+ SetUpAndDownKeysConsumed(original);
+ }
+ }
+
+EXPORT_C void CEikMfne::SetUseOverrideColors( TBool aUseOverrideColors )
+ {
+ iFlags.Assign( EUseOverrideColors, aUseOverrideColors );
+ }
+
+
+TBool CEikMfne::ConsumesUpAndDownKeys() const
+ {
+ return iFlags[ EConsumeUpAndDownKeysIndex ];
+ }
+
+TBool CEikMfne::SkinningBackground() const
+ {
+ if (iExtension)
+ return iExtension->iSkinIdForTextBackgroundColor == KErrNotFound && iFlags[ ESkinningBackground ];
+ else
+ return iFlags[ ESkinningBackground ];
+ }
+
+void CEikMfne::EvaluateSkinningBackground()
+ {
+ // Status of application skinning is latched at construction and resource change
+ iFlags.Assign( ESkinningBackground, AknsUtils::AvkonSkinEnabled() );
+ }
+
+MAknsControlContext* CEikMfne::SkinBackgroundControlContext() const
+ {
+ MAknsControlContext* context = 0;
+
+ if ( iExtension )
+ context = iExtension->iExternalSkinControlContext;
+
+ if (!context && !iFlags[ESkinBackGroundControlContextSetByApi] )
+ {
+ // Obtain the context from Object Provider
+ context = AknsDrawUtils::ControlContext( this );
+ }
+
+ return context;
+ }
+
+void CEikMfne::CreateExtensionIfRequiredL()
+ {
+ if (!iExtension )
+ {
+ iExtension = CEikMfneExtension::NewL();
+ iExtension->iEditor = this;
+ iExtension->iExtendedInputCapabilities->SetEditorType(
+ CAknExtendedInputCapabilities::EMFNEBased );
+ iExtension->iExtendedInputCapabilitiesProvider->SetMopParent(
+ this );
+ }
+ }
+
+void CEikMfne::SetCurrentField( TInt aCurrentField )
+ {
+ iCurrentField = aCurrentField;
+ }
+
+void CEikMfne::SetFirstEditableField( )
+ {
+ TBool foundEditable = EFalse;
+ for ( TInt i=0; i < iNumFields; ++i )
+ {
+ if ( iFields[i]->IsEditable() )
+ {
+ SetCurrentField(i);
+ foundEditable = ETrue;
+ break;
+ }
+ }
+ if ( !foundEditable )
+ {
+ SetCurrentField( 0 );
+ }
+ }
+//
+// CEikNumberEditor
+//
+
+EXPORT_C CEikNumberEditor::CEikNumberEditor()
+ {
+ __DECLARE_NAME(_S("CEikNumberEditor"));
+ AKNTASHOOK_ADD( this, "CEikNumberEditor" );
+ }
+
+EXPORT_C void CEikNumberEditor::ConstructL(TInt aMinimumValue, TInt aMaximumValue, TInt aInitialValue)
+ {
+ CreateFieldArrayL(1);
+ iNumber=CEikMfneNumber::NewL(*Font(), aMinimumValue, aMaximumValue, aInitialValue, 0);
+ AddField(iNumber);
+ RefreshFromLocale();
+ }
+
+void CEikNumberEditor::RefreshFromLocale()
+/**
+Update the editor from locale - ensures that digits are displayed using correct numerals for current device settings.
+@publishedComponent
+@param aFont the font of the MFNE which owns this class
+@post the next time the editor is drawn it will display the number using digit type derived from the locale information.
+*/
+ {
+ iNumber->RefreshDigitType(*Font());
+ }
+
+EXPORT_C void CEikNumberEditor::SetMinimumAndMaximum(TInt aMinimumValue, TInt aMaximumValue)
+ {
+ iNumber->SetMinimumAndMaximum(aMinimumValue, aMaximumValue, *Font());
+ }
+
+EXPORT_C void CEikNumberEditor::GetMinimumAndMaximum(TInt& aMinimumValue, TInt& aMaximumValue) const
+ {
+ iNumber->GetMinimumAndMaximum(aMinimumValue, aMaximumValue);
+ }
+
+EXPORT_C void CEikNumberEditor::SetNumber(TInt aNumber)
+ {
+ iNumber->SetValue(aNumber, *Font());
+ TRAP_IGNORE ( ReportEventL( MCoeControlObserver::EEventStateChanged ) );
+ }
+
+EXPORT_C TInt CEikNumberEditor::Number() const
+ {
+ return iNumber->Value();
+ }
+
+EXPORT_C void CEikNumberEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TInt minimumValue=aResourceReader.ReadInt32();
+ TInt maximumValue=aResourceReader.ReadInt32();
+ ConstructL(minimumValue, maximumValue, minimumValue);
+ }
+
+EXPORT_C void CEikNumberEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikMfne::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikNumberEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikNumberEditor::CEikMfne_Reserved()
+ {
+ }
+
+
+// CEikRangeEditor
+
+EXPORT_C CEikRangeEditor::CEikRangeEditor()
+ {
+ __DECLARE_NAME(_S("CEikRangeEditor"));
+ AKNTASHOOK_ADD( this, "CEikRangeEditor" );
+ }
+
+EXPORT_C void CEikRangeEditor::ConstructL(TInt aMinimumValue, TInt aMaximumValue, const SEikRange& aInitialRange, HBufC* aSeparatorText)
+ {
+ const CFont& font=*Font();
+ CreateFieldArrayL(3);
+ iLowerLimit=CEikMfneNumber::NewL(font, aMinimumValue, aMaximumValue, aInitialRange.iLowerLimit, 0);
+ AddField(iLowerLimit);
+ CEikMfneSeparator* separator=CEikMfneSeparator::NewL(NULL);
+ AddField(separator);
+ iUpperLimit=CEikMfneNumber::NewL(font, aMinimumValue, aMaximumValue, aInitialRange.iUpperLimit, 0);
+ AddField(iUpperLimit);
+ // do stuff that can only be done when all leaving functions have successfully been done
+ separator->SetText(aSeparatorText);
+
+ RefreshFromLocale();
+ }
+
+void CEikRangeEditor::RefreshFromLocale()
+ {
+ iLowerLimit->RefreshDigitType(*Font() );
+ iUpperLimit->RefreshDigitType(*Font() );
+ }
+
+EXPORT_C void CEikRangeEditor::SetMinimumAndMaximum(TInt aMinimumValue, TInt aMaximumValue)
+ {
+ const CFont& font=*Font();
+ iLowerLimit->SetMinimumAndMaximum(aMinimumValue, aMaximumValue, font);
+ iUpperLimit->SetMinimumAndMaximum(aMinimumValue, aMaximumValue, font);
+ }
+
+EXPORT_C void CEikRangeEditor::GetMinimumAndMaximum(TInt& aMinimumValue, TInt& aMaximumValue) const
+ {
+ iLowerLimit->GetMinimumAndMaximum(aMinimumValue, aMaximumValue);
+#if defined(_DEBUG)
+ TInt minimumValue;
+ TInt maximumValue;
+ iUpperLimit->GetMinimumAndMaximum(minimumValue, maximumValue);
+ __ASSERT_DEBUG((minimumValue==aMinimumValue) && (maximumValue==aMaximumValue), Panic(EEikPanicRangeEditorInconsistentMinimumAndMaximum));
+#endif
+ }
+
+EXPORT_C void CEikRangeEditor::SetRange(const SEikRange& aRange)
+ {
+ const CFont& font=*Font();
+ iLowerLimit->SetValue(aRange.iLowerLimit, font);
+ iUpperLimit->SetValue(aRange.iUpperLimit, font);
+ }
+
+EXPORT_C SEikRange CEikRangeEditor::Range() const
+ {
+ SEikRange range;
+ range.iLowerLimit=iLowerLimit->Value();
+ range.iUpperLimit=iUpperLimit->Value();
+ return range;
+ }
+
+EXPORT_C void CEikRangeEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TInt minimumValue=aResourceReader.ReadInt32();
+ TInt maximumValue=aResourceReader.ReadInt32();
+ HBufC* separatorText=aResourceReader.ReadHBufCL();
+ CleanupStack::PushL(separatorText);
+ SEikRange initialRange;
+ initialRange.iLowerLimit=maximumValue;
+ initialRange.iUpperLimit=maximumValue;
+ ConstructL(minimumValue, maximumValue, initialRange, separatorText);
+ CleanupStack::Pop();
+ }
+
+void CEikRangeEditor::FieldIsAboutToBeDeHighlighted(CEikMfneField* aField, TBool& aDrawAllFields)
+ {
+ const CFont& font=*Font();
+ if (aField==iLowerLimit)
+ {
+ TInt lowerLimitValue=iLowerLimit->Value();
+ if (iUpperLimit->Value()<lowerLimitValue)
+ {
+ iUpperLimit->SetValue(lowerLimitValue, font);
+ aDrawAllFields=ETrue;
+ }
+ }
+ else if (aField==iUpperLimit)
+ {
+ TInt upperLimitValue=iUpperLimit->Value();
+ if (iLowerLimit->Value()>upperLimitValue)
+ {
+ iLowerLimit->SetValue(upperLimitValue, font);
+ aDrawAllFields=ETrue;
+ }
+ }
+ }
+
+EXPORT_C void CEikRangeEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikMfne::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikRangeEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikRangeEditor::CEikMfne_Reserved()
+ {
+ }
+
+
+// CTimeEditor
+
+class CTimeEditor : public CBase
+ {
+public:
+ enum
+ {
+ EWithoutSecondsField =1, // same as EEikTimeWithoutSecondsField,
+ EWithoutPopoutCalendar =2, // same as EEikDateWithoutPopoutCalendar,
+ EWithoutHoursField =4, // same as EEikTimeWithoutHoursField,
+ EForce24HourFormat =8, // same as EEikTimeForce24HourFormat,
+ ETimeZoneOffsetFormat =16,// same as EEikTimeZoneOffsetFormat,
+ };
+public:
+ CTimeEditor();
+ TInt NumFieldsRequired(TUint32 aFlags);
+ void ConstructFieldsL(CEikMfne& aOwner, const TTime& aInitialTime, const CFont& aFont);
+ void SetTime(const TTime& aTime, const CFont& aFont);
+ void SetMinMax(TInt aHourMin,TInt aHourMax,TInt aMinuteMin,TInt aMinuteMax,
+ TInt aSecondMin,TInt aSecondMax,const CFont& aFont);
+ TTime Time() const;
+ void SetUninitialised(TBool aUninitialised);
+ TBool IsUninitialised() const;
+ void RefreshFromLocale(const CFont& aFont);
+
+private:
+ void AddAmPmFieldsIfNecessaryL(CEikMfne& aOwner, TAmPm aAmPm, TLocalePos aPos);
+private:
+ enum // these are needed in case the OS locale changes between NumFieldsRequired and ConstructFieldsL being called
+ {
+ EIn12HourFormat =0x20,
+ ESpaceBeforeAmPm =0x40,
+ EAmPmIsPositionedBeforeTime =0x80,
+ };
+private:
+ TUint32 iFlags;
+ // none of these pointers owns anything
+ CEikMfneNumber* iSecond; // may be NULL;
+ CEikMfneNumber* iMinute;
+ CEikMfneNumber* iHour; // may be NULL;
+ CEikMfneSymbol* iAmPm; // may be NULL;
+ };
+
+CTimeEditor::CTimeEditor()
+ {
+ __DECLARE_NAME(_S("CTimeEditor"));
+ }
+
+TInt CTimeEditor::NumFieldsRequired(TUint32 aFlags)
+ {
+ iFlags=aFlags;
+ TInt numFieldsRequired=1; // 1 for minute
+ if (~iFlags&EWithoutSecondsField)
+ numFieldsRequired+=2; // 2 for separator and second
+ if (~iFlags&EWithoutHoursField)
+ numFieldsRequired+=2; // 2 for hour and separator
+ if (~iFlags&EForce24HourFormat&&~iFlags&ETimeZoneOffsetFormat)
+ {
+ TLocale locale;
+ TTimeFormat timeFormat=locale.TimeFormat();
+ __ASSERT_DEBUG((timeFormat==ETime12) || (timeFormat==ETime24), Panic(EEikPanicDateEditorBadTimeFormat));
+ if (timeFormat==ETime12)
+ {
+ if (locale.AmPmSymbolPosition()==ELocaleBefore)
+ iFlags|=EAmPmIsPositionedBeforeTime;
+ if (locale.AmPmSpaceBetween())
+ {
+ ++numFieldsRequired;
+ iFlags|=ESpaceBeforeAmPm;
+ }
+ ++numFieldsRequired;
+ iFlags|=EIn12HourFormat;
+ }
+ }
+ return numFieldsRequired;
+ }
+
+void CTimeEditor::RefreshFromLocale(const CFont& aFont)
+/**
+Update the tier editor from locale - ensures that digits are displayed using correct numerals for current device settings.
+@publishedComponent
+@param aFont the font of the MFNE which owns this class
+@post the next time the editor is drawn it will display the number using digit type derived from the locale information.
+*/
+ {
+ if(iSecond)
+ iSecond->RefreshDigitType(aFont);
+
+ if(iMinute)
+ iMinute->RefreshDigitType(aFont);
+
+ if(iHour)
+ iHour->RefreshDigitType(aFont);
+ }
+
+void CTimeEditor::ConstructFieldsL(CEikMfne& aOwner, const TTime& aInitialTime, const CFont& aFont)
+ {
+ TDateTime initialTime=aInitialTime.DateTime();
+ TLocale locale;
+ TInt timeSeparatorIndex=1;
+ const TUint32 flags=CEikMfneNumber::EFillWithLeadingZeros|CEikMfneNumber::EPreserveOldWidthBeforeEditing;
+ TInt hour=initialTime.Hour();
+ TAmPm amPm=(hour<12)? EAm: EPm;
+ TInt minimumHour=0;
+ TInt maximumHour=23;
+ if (iFlags&EIn12HourFormat)
+ {
+ minimumHour=1;
+ maximumHour=12;
+ hour%=12;
+ if (hour==0)
+ hour=12;
+ }
+ if (iFlags&ETimeZoneOffsetFormat)
+ {
+ minimumHour=0;
+ maximumHour=12;
+ hour=0;
+ }
+ // create and push the time elements in the opposite order to the order in which they will be added so that they are popped off in the correct order
+ AddAmPmFieldsIfNecessaryL(aOwner, amPm, ELocaleBefore);
+ TBool amIsBefor(iFlags&EAmPmIsPositionedBeforeTime);
+ if (~iFlags&EWithoutSecondsField)
+ {
+ iSecond=CEikMfneNumber::NewL(aFont, 0, KMaxMinSecValue, initialTime.Second(), flags);
+ CleanupStack::PushL(iSecond); // this needs to be pushed as it would not be destroyed by the class' destructor
+ }
+ iMinute=CEikMfneNumber::NewL(aFont, 0, KMaxMinSecValue, initialTime.Minute(), flags);
+ CleanupStack::PushL(iMinute); // this needs to be pushed as it would not be destroyed by the class' destructor
+ if (~iFlags&EWithoutHoursField)
+ {
+ //iHour=CEikMfneNumber::NewL(aFont, minimumHour, maximumHour, hour, flags&~((iFlags&EIn12HourFormat)? CEikMfneNumber::EFillWithLeadingZeros: 0));
+ iHour=CEikMfneNumber::NewL(aFont, minimumHour, maximumHour, hour,flags);
+ CleanupStack::PushL(iHour); // this needs to be pushed as it would not be destroyed by the class' destructor
+ // add hour
+ aOwner.AddField(iHour);
+ CleanupStack::Pop();
+ // add the first separator
+ HBufC* firstSeparatorText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ firstSeparatorText->Des().Append(locale.TimeSeparator(timeSeparatorIndex++));
+ aOwner.AddField(CEikMfneSeparator::NewL(firstSeparatorText));
+ CleanupStack::Pop();
+ }
+ // add minute
+ aOwner.AddField(iMinute);
+ CleanupStack::Pop();
+ if (~iFlags&EWithoutSecondsField)
+ {
+ // add the second separator
+ HBufC* secondSeparatorText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ secondSeparatorText->Des().Append(locale.TimeSeparator(timeSeparatorIndex++));
+ aOwner.AddField(CEikMfneSeparator::NewL(secondSeparatorText));
+ CleanupStack::Pop();
+ // add second
+ aOwner.AddField(iSecond);
+ CleanupStack::Pop();
+ }
+ if ( !amIsBefor )
+ {
+ AddAmPmFieldsIfNecessaryL(aOwner, amPm, ELocaleAfter);
+ }
+ else
+ {
+ // if am is added before time fields, set first editable time field
+ // as highlighted
+ for ( TInt i = 1; aOwner.Field( i ) != NULL; i++ )
+ {
+ if ( aOwner.Field( i )->IsEditable() )
+ {
+ aOwner.SetCurrentField( i );
+ break;
+ }
+ }
+ }
+ }
+
+void CTimeEditor::SetTime(const TTime& aTime, const CFont& aFont)
+ {
+ TDateTime time=aTime.DateTime();
+ if (iSecond)
+ iSecond->SetValue(time.Second(), aFont);
+ iMinute->SetValue(time.Minute(), aFont);
+ TInt hour=time.Hour();
+ if (iAmPm)
+ {
+ TAmPm amPm=(hour<12)? EAm: EPm;
+ hour%=12;
+ if (hour==0)
+ hour=12;
+ iAmPm->SetCurrentSymbolicItemToId(amPm);
+ }
+ if(iHour)
+ iHour->SetValue(hour, aFont);
+ }
+
+void CTimeEditor::SetMinMax(TInt /*aHourMin*/,TInt /*aHourMax*/,TInt /*aMinuteMin*/,TInt /*aMinuteMax*/,
+ TInt /*aSecondMin*/,TInt /*aSecondMax*/,const CFont& /*aFont*/)
+ {
+ /*iHour->SetMinimumAndMaximum(aHourMin, aHourMax, aFont);
+ iMinute->SetMinimumAndMaximum(aMinuteMin, aMinuteMax, aFont);
+ if (iSecond!=NULL)
+ iSecond->SetMinimumAndMaximum(aSecondMin, aSecondMax, aFont);*/
+ }
+
+TTime CTimeEditor::Time() const
+ {
+ TInt dayValue=0;
+ TInt hourValue=iHour?iHour->Value():0;
+ if (iAmPm)
+ {
+ hourValue%=12;
+ if (iAmPm->IdOfCurrentSymbolicItem()==EPm)
+ hourValue+=12;
+ }
+ return TTime(TDateTime(0, EJanuary, dayValue, hourValue, iMinute->Value(), iSecond? iSecond->Value(): 0, 0));
+ }
+
+void CTimeEditor::AddAmPmFieldsIfNecessaryL(CEikMfne& aOwner, TAmPm aAmPm, TLocalePos aPos)
+ {
+ if ( iFlags&EIn12HourFormat )
+ {
+ // Test the am/pm symbol
+ TAmPmName amName(EAm);
+ TAmPmName pmName(EPm);
+
+ TBool stackedBefore = iFlags&EAmPmIsPositionedBeforeTime;
+
+ // Use the directionality of the first character of the localized Am symbol
+ // to determine if "Before" means stacked first or last.
+ TChar firstChar('A') ;
+ if (amName.Length()>0)
+ {
+ firstChar = amName[0];
+ TInt cat = firstChar.GetBdCategory();
+ // RTL indicates that we have to put it stack as if after.
+ if ( cat == TChar::ERightToLeft || cat == TChar::ERightToLeftArabic )
+ stackedBefore = !(iFlags&EAmPmIsPositionedBeforeTime);
+ }
+
+ if ( ( stackedBefore && ( aPos==ELocaleBefore ) )
+ || ( !stackedBefore && (aPos!=ELocaleBefore ) ) )
+ {
+ CEikMfneSeparator* space=NULL;
+ if (iFlags&ESpaceBeforeAmPm)
+ {
+ // add separator consisting of a space
+ HBufC* spaceSeparatorText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ spaceSeparatorText->Des().Append(TChar(' '));
+ space=CEikMfneSeparator::NewL(spaceSeparatorText);
+ CleanupStack::Pop();
+ CleanupStack::PushL(space);
+ }
+ iAmPm=CEikMfneSymbol::NewL(2);
+ CleanupStack::PushL(iAmPm); // this needs to be pushed as it would not be destroyed by the class' destructor
+
+ // add the am symbol
+ HBufC* amText=HBufC::NewLC(amName.Length()); // also pushes on to CleanupStack
+ *amText=amName;
+ iAmPm->AddSymbolicItem(CEikMfneSymbol::CItem::NewL(EAm, amName[0], amText), aAmPm==EAm); // !! IS amName[0] SUFFICIENT FOR THE KEY TO MATCH?
+ CleanupStack::Pop();
+ // add the pm symbol
+ HBufC* pmText=HBufC::NewLC(pmName.Length()); // also pushes on to CleanupStack
+ *pmText=pmName;
+ iAmPm->AddSymbolicItem(CEikMfneSymbol::CItem::NewL(EPm, pmName[0], pmText), aAmPm==EPm); // !! IS pmName[0] SUFFICIENT FOR THE KEY TO MATCH?
+ CleanupStack::Pop((iFlags&ESpaceBeforeAmPm)? 3: 2);
+ if ( (!stackedBefore) && space )
+ aOwner.AddField(space);
+ aOwner.AddField(iAmPm);
+ if ( stackedBefore && space )
+ aOwner.AddField(space);
+ }
+ }
+ }
+
+void CTimeEditor::SetUninitialised(TBool aUninitialised)
+ {
+ if (iSecond)
+ iSecond->SetUninitialised(aUninitialised);
+ if (iMinute)
+ iMinute->SetUninitialised(aUninitialised);
+ if (iHour)
+ iHour->SetUninitialised(aUninitialised);
+ if (iAmPm)
+ iAmPm->SetUninitialised(aUninitialised);
+ }
+
+TBool CTimeEditor::IsUninitialised() const
+ {
+ return
+ (iSecond && iSecond->IsUninitialised()) ||
+ (iMinute && iMinute->IsUninitialised()) ||
+ (iHour && iHour->IsUninitialised()) ||
+ (iAmPm && iAmPm->IsUninitialised());
+ }
+
+
+// CDateEditor
+
+class CDateEditor : public CBase
+ {
+public:
+ CDateEditor(CEikMfne& aOwner, MEikCalendarObserver* aCalendarObserver, TInt aFirstFieldPosition);
+ TInt NumFieldsRequired() const;
+ void ConstructFieldsL(TInt aMinimumYear, TInt aMaximumYear, const TTime& aInitialDate, TBool aWithoutPopoutCalendar, CEikonEnv& aEikonEnv, const CFont& aFont);
+ void SetMinimumAndMaximum(TInt aMinimumYear, TInt aMaximumYear, const CFont& aFont);
+ void SetDate(const TTime& aDate, const CFont& aFont);
+ TTime Date(const TTime* aTime=NULL) const;
+ TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType);
+ void PrepareForFocusLossL();
+ void CreatePopoutIfRequiredL();
+ void ExecuteCalendarL();
+
+ void SetUninitialised(TBool aUninitialised);
+ TBool IsUninitialised() const;
+ void RefreshFromLocale(const CFont& aFont);
+
+ static TInt ValidateCallBack( TAny* aPtr );
+
+public:
+ TInt Year() const;
+ TInt Month() const;
+ TInt Day() const;
+ TBool IsTextNull() const;
+ void UpdateMaxDay( const CFont& aFont );
+private:
+ class RDateElements // objects of this class must be pushed on to the cleanup-stack
+ {
+ public:
+ RDateElements();
+ void Add(CEikMfneNumber* aDateElement, TInt aPosition);
+ CEikMfneNumber* Next();
+ private:
+ static void Cleanup(TAny* aThis);
+ public:
+ inline operator TCleanupItem() {return TCleanupItem(Cleanup, this);}
+ private:
+ enum {EMaximumNumberOfDateElements=3};
+ private:
+ CEikMfneNumber* iDateElements[EMaximumNumberOfDateElements];
+ };
+
+private:
+ /**
+ * Called to see if the date fields need to be re-ordered because the
+ * number format causes logical to visual reordering in text.
+ */
+ static TBool DateFieldReOrderingNeeded();
+
+private:
+ CEikMfne& iOwner;
+ MEikCalendarObserver* iCalendarObserver;
+ TBool iWithoutPopoutCalendar;
+ // none of these pointers owns anything
+ CEikMfneNumber* iDay;
+ CEikMfneNumber* iMonth;
+ CEikMfneNumber* iYear;
+ TInt iDayFieldPosition;
+ TInt iFirstFieldPosition;
+ };
+
+CDateEditor::CDateEditor(CEikMfne& aOwner,MEikCalendarObserver* aCalendarObserver,TInt aFirstFieldPosition)
+ :iOwner(aOwner),
+ iCalendarObserver(aCalendarObserver),
+ iFirstFieldPosition(aFirstFieldPosition)
+ {
+ __DECLARE_NAME(_S("CDateEditor"));
+ }
+
+TInt CDateEditor::NumFieldsRequired() const
+ {
+ return 5;
+ }
+
+TBool CDateEditor::DateFieldReOrderingNeeded()
+ {
+ TBool reorderingNeeded(EFalse);
+
+ TLocale locale;
+
+ // Reordering needed if it is RTL, we have arabic digits and if the separator is not
+ // numeric separator.
+ TLanguage language = (TLanguage)(User::Language() & KAknLanguageMask);
+ if ( TBidiText::ScriptDirectionality( language ) == TBidiText::ERightToLeft)
+ {
+ TInt digitType = AknTextUtils::NumericEditorDigitType();
+ if ( digitType == EDigitTypeArabicIndic )
+ //|| digitType == EDigitTypeEasternArabicIndic ) // Urdu has numbers bidi=EN (LTR)
+ // no re-ordering is needed
+ {
+ TChar sep = locale.DateSeparator(1);
+ if ( sep.GetBdCategory() != TChar::ECommonNumberSeparator )
+ reorderingNeeded = ETrue;
+ }
+ }
+ return reorderingNeeded;
+ }
+
+void CDateEditor::ConstructFieldsL(TInt aMinimumYear, TInt aMaximumYear, const TTime& aInitialDate, TBool aWithoutPopoutCalendar, CEikonEnv& /*aEikonEnv*/, const CFont& aFont)
+ {
+ iWithoutPopoutCalendar=aWithoutPopoutCalendar;
+ const TUint32 flags=CEikMfneNumber::EFillWithLeadingZeros|CEikMfneNumber::EPreserveOldWidthBeforeEditing;
+ TLocale locale;
+ TDateFormat dateFormat=locale.DateFormat();
+ TInt dateSeparatorIndex=1;
+ TInt dayPosition=0, monthPosition=0, yearPosition=0; // dummy initializations to prevent compiler warnings
+
+ // Implement switch in layout owning to locale:
+ if ( DateFieldReOrderingNeeded() )
+ {
+ switch (dateFormat)
+ {
+ case EDateAmerican:
+ monthPosition=2;
+ dayPosition=1;
+ yearPosition=0;
+ break;
+ case EDateEuropean:
+ dayPosition=2;
+ monthPosition=1;
+ yearPosition=0;
+ break;
+ case EDateJapanese:
+ yearPosition=2;
+ monthPosition=1;
+ dayPosition=0;
+ break;
+#if defined(_DEBUG)
+ default:
+ Panic(EEikPanicDateEditorBadDateFormat);
+ break;
+#endif
+ }
+ }
+ else
+ {
+ switch (dateFormat)
+ {
+ case EDateAmerican:
+ monthPosition=0;
+ dayPosition=1;
+ yearPosition=2;
+ break;
+ case EDateEuropean:
+ dayPosition=0;
+ monthPosition=1;
+ yearPosition=2;
+ break;
+ case EDateJapanese:
+ yearPosition=0;
+ monthPosition=1;
+ dayPosition=2;
+ break;
+#if defined(_DEBUG)
+ default:
+ Panic(EEikPanicDateEditorBadDateFormat);
+ break;
+#endif
+ }
+ }
+
+ TDateTime initialDate=aInitialDate.DateTime();
+ RDateElements dateElements;
+ CleanupStack::PushL(dateElements);
+ iDay=CEikMfneNumber::NewL(aFont, 1, 31, initialDate.Day()+1, flags);
+
+ iDayFieldPosition = dayPosition * 2;
+ dateElements.Add(iDay, dayPosition);
+ iMonth=CEikMfneNumber::NewL(aFont, 1, 12, initialDate.Month()+1, flags);
+ dateElements.Add(iMonth, monthPosition);
+ iYear=CEikMfneNumber::NewL(aFont, aMinimumYear, aMaximumYear, initialDate.Year(), flags|CEikMfneNumber::ERepresentsYear);
+ dateElements.Add(iYear, yearPosition);
+ // add first date element
+ iOwner.AddField(dateElements.Next());
+ // add first separator
+ HBufC* firstSeparatorText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ firstSeparatorText->Des().Append(locale.DateSeparator(dateSeparatorIndex++));
+ iOwner.AddField(CEikMfneSeparator::NewL(firstSeparatorText));
+ CleanupStack::Pop(firstSeparatorText);
+
+ // add second date element
+ iOwner.AddField(dateElements.Next());
+ // add second separator
+ HBufC* secondSeparatorText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ secondSeparatorText->Des().Append(locale.DateSeparator(dateSeparatorIndex++));
+ iOwner.AddField(CEikMfneSeparator::NewL(secondSeparatorText));
+ CleanupStack::Pop(secondSeparatorText);
+
+ // add third date element
+ iOwner.AddField(dateElements.Next());
+ CleanupStack::PopAndDestroy(); //
+ iOwner.SetValidateCallBack( TCallBack( ValidateCallBack, this ) );
+ }
+
+void CDateEditor::RefreshFromLocale(const CFont& aFont)
+/**
+Update the date editor from locale - ensursed that digits are displayed using correct numerals for current device settings.
+@publishedComponent
+@param aFont the font of the MFNE which owns this class
+@post the next time the editor is drawn it will display the number using digit type derived from the locale information.
+*/
+ {
+ iDay->RefreshDigitType(aFont);
+ iMonth->RefreshDigitType(aFont);
+ iYear->RefreshDigitType(aFont);
+ }
+
+void CDateEditor::SetMinimumAndMaximum(TInt aMinimumYear, TInt aMaximumYear, const CFont& aFont)
+ {
+ iYear->SetMinimumAndMaximum(aMinimumYear, aMaximumYear, aFont);
+ }
+
+void CDateEditor::SetDate(const TTime& aDate, const CFont& aFont)
+ {
+ TDateTime date=aDate.DateTime();
+ iDay->SetValue(date.Day()+1, aFont);
+ iMonth->SetValue(date.Month()+1, aFont);
+ iYear->SetValue(date.Year(), aFont);
+ }
+
+TTime CDateEditor::Date(const TTime* aTime) const
+ {
+ TInt hour=0;
+ TInt minute=0;
+ TInt second=0;
+ if (aTime)
+ {
+ TDateTime time=aTime->DateTime();
+ hour=time.Hour();
+ minute=time.Minute();
+ second=time.Second();
+ }
+ TDateTime date;
+ TInt day = iDay->Value();
+ if (date.Set(iYear->Value(), (TMonth)(iMonth->Value()-1), day-1, 0, 0, 0, 0)!=KErrNone)
+ {
+ TInt maximumDay = Time::DaysInMonth( iYear->Value(), (TMonth)(iMonth->Value()-1));
+ if (day > maximumDay)
+ {
+ day = maximumDay;
+ iDay->SetValue(maximumDay, *(iOwner.Font()));
+ iOwner.HighlightField(iDayFieldPosition + iFirstFieldPosition);
+ }
+// AVKON - should not leave in Date() function. Day value is fixed instead.
+ }
+ return TTime(TDateTime(iYear->Value(), (TMonth)(iMonth->Value()-1), day-1, hour, minute, second, 0));
+ }
+
+TKeyResponse CDateEditor::OfferKeyEventL(const TKeyEvent& /*aKeyEvent*/, TEventCode /*aType*/)
+ {
+// AVKON - we do not want any behavior from up/down or tab key (which was here before)
+ return EKeyWasNotConsumed;
+ }
+
+void CDateEditor::PrepareForFocusLossL()
+ {
+ TDateTime date;
+
+ if (date.Set(iYear->Value(), (TMonth)(iMonth->Value()-1), iDay->Value()-1, 0, 0, 0, 0)!=KErrNone)
+ {
+ TInt maximumDay = Time::DaysInMonth( iYear->Value(), (TMonth)(iMonth->Value()-1));
+ if ( iDay->Value() > maximumDay )
+ {
+ iDay->SetValue(maximumDay, *(iOwner.Font()));
+ iOwner.HighlightField(iDayFieldPosition + iFirstFieldPosition);
+ iOwner.ReportUpdate();
+ }
+ iOwner.DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_DATE_INVALID, date);
+ //aEikonEnv.LeaveWithInfoMsg(R_EIK_TBUF_DATE_INVALID);
+ }
+ }
+
+void CDateEditor::CreatePopoutIfRequiredL()
+ {
+ if (!iWithoutPopoutCalendar)
+ ExecuteCalendarL();
+ }
+
+void CDateEditor::ExecuteCalendarL()
+ {
+ if( AknLayoutUtils::PenEnabled() )
+ {
+ // must not do anything when Touch UI is enabled
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+/* Build Thinning
+ CEikCalendar* calendar=new(ELeave) CEikCalendar;
+ calendar->SetCalendarObserver(iCalendarObserver);
+ calendar->ExecuteLD(R_EIK_ONE_MONTH_CALENDAR);
+*/
+ }
+
+TInt CDateEditor::Year() const
+ {
+ return(iYear->Value());
+ }
+
+TInt CDateEditor::Month() const
+ {
+ return(iMonth->Value());
+ }
+
+TInt CDateEditor::Day() const
+ {
+ return(iDay->Value());
+ }
+
+TBool CDateEditor::IsTextNull() const
+ {
+ return ( iYear->IsTextNull() | iMonth->IsTextNull() | iDay->IsTextNull());
+ }
+
+void CDateEditor::UpdateMaxDay( const CFont& aFont )
+ {
+ TInt maximumDay = Time::DaysInMonth( iYear->Value(), (TMonth)(iMonth->Value()-1));
+ iDay->SetMinimumAndMaximum( 1, maximumDay, aFont );
+ }
+
+// CDateEditor::RDateElements
+
+CDateEditor::RDateElements::RDateElements()
+ {
+ for (TInt i=0; i<EMaximumNumberOfDateElements; ++i)
+ iDateElements[i]=NULL;
+ }
+
+void CDateEditor::RDateElements::Add(CEikMfneNumber* aDateElement, TInt aPosition)
+ {
+ __ASSERT_DEBUG((aPosition>=0) && (aPosition<EMaximumNumberOfDateElements), Panic(EEikPanicDateEditorBadDateElementPosition));
+ iDateElements[aPosition]=aDateElement;
+ }
+
+CEikMfneNumber* CDateEditor::RDateElements::Next()
+ {
+ for (TInt i=0; i<EMaximumNumberOfDateElements; ++i)
+ if (iDateElements[i])
+ {
+ CEikMfneNumber* dateElement=iDateElements[i];
+ iDateElements[i]=NULL;
+ return dateElement;
+ }
+#if defined(_DEBUG)
+ Panic(EEikPanicDateEditorNoMoreDateElements);
+#endif
+ return NULL; // dummy return to prevent compiler error
+ }
+
+void CDateEditor::RDateElements::Cleanup(TAny* aThis)
+ {
+ for (TInt i=0; i<EMaximumNumberOfDateElements; ++i)
+ delete ((RDateElements*)aThis)->iDateElements[i];
+ }
+
+void CDateEditor::SetUninitialised(TBool aUninitialised)
+ {
+ if (iDay)
+ iDay->SetUninitialised(aUninitialised);
+ if (iMonth)
+ iMonth->SetUninitialised(aUninitialised);
+ if (iYear)
+ iYear->SetUninitialised(aUninitialised);
+ }
+
+TBool CDateEditor::IsUninitialised() const
+ {
+ return
+ (iDay && iDay->IsUninitialised()) ||
+ (iMonth && iMonth->IsUninitialised()) ||
+ (iYear && iYear->IsUninitialised());
+ }
+
+TInt CDateEditor::ValidateCallBack( TAny* aPtr )
+ {
+ CDateEditor* edit( static_cast<CDateEditor*>( aPtr ) );
+ TRAPD( err, edit->PrepareForFocusLossL() );
+ edit->UpdateMaxDay( *(CEikonEnv::Static()->NormalFont()));
+ return err;
+ }
+
+// CEikTimeEditor
+
+EXPORT_C CEikTimeEditor::CEikTimeEditor()
+ {
+ __DECLARE_NAME(_S("CEikTimeEditor"));
+ AKNTASHOOK_ADD( this, "CEikTimeEditor" );
+ }
+
+EXPORT_C CEikTimeEditor::~CEikTimeEditor()
+ {
+ AKNTASHOOK_REMOVE();
+ delete iTimeEditor;
+ }
+
+EXPORT_C void CEikTimeEditor::ConstructL(const TTime& aMinimumTime, const TTime& aMaximumTime, const TTime& aInitialTime, TUint32 aFlags)
+ {
+ iTimeEditor=new(ELeave) CTimeEditor;
+ //CreateFieldArrayL(iTimeEditor->NumFieldsRequired(aWithoutSecondsField? CTimeEditor::EWithoutSecondsField: 0));
+ CreateFieldArrayL(iTimeEditor->NumFieldsRequired(aFlags));
+ iTimeEditor->ConstructFieldsL(*this, aInitialTime, *Font());
+ iTimeEditor->RefreshFromLocale(*Font());
+ DoSetMinimumAndMaximum(aMinimumTime, aMaximumTime);
+ }
+
+EXPORT_C void CEikTimeEditor::SetMinimumAndMaximum(const TTime& aMinimumTime, const TTime& aMaximumTime)
+ {
+ // __ASSERT_ALWAYS((aMinimumTime>=iMinimumTime) && (aMaximumTime<=iMaximumTime), Panic(EEikPanicTimeEditorBadMinimumAndMaximum1));
+ DoSetMinimumAndMaximum(aMinimumTime, aMaximumTime);
+ }
+
+EXPORT_C void CEikTimeEditor::GetMinimumAndMaximum(TTime& aMinimumTime, TTime& aMaximumTime) const
+ {
+ aMinimumTime=iMinimumTime;
+ aMaximumTime=iMaximumTime;
+ }
+
+EXPORT_C void CEikTimeEditor::SetTime(const TTime& aTime)
+ {
+ iTimeEditor->SetTime(aTime, *Font());
+ TRAP_IGNORE ( ReportEventL( MCoeControlObserver::EEventStateChanged ) );
+ }
+
+EXPORT_C TTime CEikTimeEditor::Time() const
+ {
+ return iTimeEditor->Time();
+ }
+
+void CEikTimeEditor::SetTTime(const TTime& aTime)
+ {
+ SetTime(aTime);
+ }
+
+TTime CEikTimeEditor::GetTTime() const
+ {
+ return(Time());
+ }
+
+EXPORT_C void CEikTimeEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TTime minimumTime=ReadTime(aResourceReader);
+ TTime maximumTime=ReadTime(aResourceReader);
+ TUint32 flags=aResourceReader.ReadUint8();
+ ConstructL(minimumTime, maximumTime, maximumTime, flags);
+ }
+
+EXPORT_C void CEikTimeEditor::PrepareForFocusLossL()
+ {
+ CEikMfne::PrepareForFocusLossL();
+ TTime time=Time();
+ if (time<iMinimumTime)
+ {
+ SetTime(iMinimumTime);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_BEFORE_EARLIEST_ALLOWED_TIME, iMinimumTime);
+ }
+ else if (time>iMaximumTime)
+ {
+ SetTime(iMaximumTime);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_AFTER_LATEST_ALLOWED_TIME, iMaximumTime);
+ }
+ }
+
+void CEikTimeEditor::DoSetMinimumAndMaximum(const TTime& aMinimumTime, const TTime& aMaximumTime)
+ {
+ __ASSERT_ALWAYS(aMinimumTime<=aMaximumTime, Panic(EEikPanicTimeEditorBadMinimumAndMaximum2));
+ iMinimumTime=aMinimumTime;
+ iMaximumTime=aMaximumTime;
+ TTime time=Time();
+ if (time<iMinimumTime)
+ SetTime(iMinimumTime);
+ else if (time>iMaximumTime)
+ SetTime(iMaximumTime);
+ }
+
+EXPORT_C void CEikTimeEditor::CEikMfne_Reserved()
+ {
+ }
+
+EXPORT_C void CEikTimeEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikTTimeEditor::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikTimeEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikTimeEditor::SetUninitialised(TBool aUninitialised)
+ {
+ iTimeEditor->SetUninitialised(aUninitialised);
+ }
+
+EXPORT_C TBool CEikTimeEditor::IsUninitialised() const
+ {
+ return iTimeEditor->IsUninitialised();
+ }
+
+// CEikDateEditor
+
+EXPORT_C CEikDateEditor::CEikDateEditor()
+ {
+ __DECLARE_NAME(_S("CEikDateEditor"));
+ AKNTASHOOK_ADD( this, "CEikDateEditor" );
+ }
+
+EXPORT_C CEikDateEditor::~CEikDateEditor()
+ {
+ AKNTASHOOK_REMOVE();
+ delete iDateEditor;
+ }
+
+EXPORT_C void CEikDateEditor::ConstructL(const TTime& aMinimumDate, const TTime& aMaximumDate, const TTime& aInitialDate, TBool aWithoutPopoutCalendar)
+ {
+ __ASSERT_DEBUG(KAknMinimumDate<=aMinimumDate, Panic(EEikPanicDateEditorBadMinimum));
+ __ASSERT_DEBUG(aMaximumDate<=KAknMaximumDate, Panic(EEikPanicDateEditorBadMaximum));
+ TTime minDate = Max(KAknMinimumDate, aMinimumDate);
+ TTime maxDate = Min(aMaximumDate, KAknMaximumDate);
+ iDateEditor=new(ELeave) CDateEditor(*this,this,0);
+ CreateFieldArrayL(iDateEditor->NumFieldsRequired());
+ iDateEditor->ConstructFieldsL(minDate.DateTime().Year(), maxDate.DateTime().Year(), aInitialDate, aWithoutPopoutCalendar, *iEikonEnv, *Font());
+ DoSetMinimumAndMaximum(minDate, maxDate);
+ iDateEditor->RefreshFromLocale(*Font());
+ }
+
+EXPORT_C void CEikDateEditor::SetMinimumAndMaximum(const TTime& aMinimumDate, const TTime& aMaximumDate)
+ {
+ __ASSERT_DEBUG(KAknMinimumDate<=aMinimumDate, Panic(EEikPanicDateEditorBadMinimum));
+ __ASSERT_DEBUG(aMaximumDate<=KAknMaximumDate, Panic(EEikPanicDateEditorBadMaximum));
+ TTime minDate = Max(KAknMinimumDate, aMinimumDate);
+ TTime maxDate = Min(aMaximumDate, KAknMaximumDate);
+ iDateEditor->SetMinimumAndMaximum(minDate.DateTime().Year(), maxDate.DateTime().Year(), *Font());
+ DoSetMinimumAndMaximum(minDate, maxDate);
+ }
+
+EXPORT_C void CEikDateEditor::GetMinimumAndMaximum(TTime& aMinimumDate, TTime& aMaximumDate) const
+ {
+ aMinimumDate=iMinimumDate;
+ aMaximumDate=iMaximumDate;
+ }
+
+EXPORT_C void CEikDateEditor::SetDate(const TTime& aDate)
+ {
+ iDateEditor->SetDate(aDate, *Font());
+ TRAP_IGNORE ( ReportEventL( MCoeControlObserver::EEventStateChanged ) );
+ }
+
+EXPORT_C TTime CEikDateEditor::Date() const
+ {
+ return iDateEditor->Date();
+ }
+
+void CEikDateEditor::SetTTime(const TTime& aTime)
+ {
+ SetDate(aTime);
+ }
+
+TTime CEikDateEditor::GetTTime() const
+ {
+ return(Date());
+ }
+
+EXPORT_C TKeyResponse CEikDateEditor::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
+ {
+ if (iDateEditor->OfferKeyEventL(aKeyEvent, aType)==EKeyWasConsumed)
+ return EKeyWasConsumed;
+ if ( ( aType==EEventKey)&&
+ ( aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyRightArrow ||
+ aKeyEvent.iCode == EKeyDownArrow || aKeyEvent.iCode == EKeyUpArrow ) )
+ {
+ iDateEditor->UpdateMaxDay( *Font() );
+ }
+
+ return CEikMfne::OfferKeyEventL(aKeyEvent, aType);
+ }
+
+EXPORT_C void CEikDateEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TTime minimumDate=ReadDate(aResourceReader);
+ TTime maximumDate=ReadDate(aResourceReader);
+ TUint32 flags=aResourceReader.ReadUint8();
+ ConstructL(minimumDate, maximumDate, maximumDate, flags&EEikDateWithoutPopoutCalendar);
+ }
+
+EXPORT_C void CEikDateEditor::PrepareForFocusLossL()
+ {
+ CEikMfne::PrepareForFocusLossL();
+ iDateEditor->PrepareForFocusLossL();
+ TTime date=Date();
+ if (date<iMinimumDate)
+ {
+ SetDate(iMinimumDate);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_BEFORE_EARLIEST_ALLOWED_DATE, iMinimumDate);
+ }
+ else if (date>iMaximumDate)
+ {
+ SetDate(iMaximumDate);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_AFTER_LATEST_ALLOWED_DATE, iMaximumDate);
+ }
+ }
+
+void CEikDateEditor::CreatePopoutIfRequiredL()
+ {
+ iDateEditor->CreatePopoutIfRequiredL();
+ }
+
+void CEikDateEditor::GetMinimumAndMaximumAndInitialDatesForCalendarL(TTime& aMinimumDate, TTime& aMaximumDate, TTime& aInitialDate) const
+ {
+ aMinimumDate=iMinimumDate;
+ aMaximumDate=iMaximumDate;
+ TDateTime date;
+ if (iDateEditor->IsTextNull())
+ CEikMfne::LeaveWithAlert(R_EIK_TBUF_DATE_INVALID);
+ if (date.Set(iDateEditor->Year(), (TMonth)(iDateEditor->Month()-1), iDateEditor->Day()-1, 0, 0, 0, 0)!=KErrNone)
+ CEikMfne::LeaveWithAlert(R_EIK_TBUF_DATE_INVALID);
+ aInitialDate=iDateEditor->Date();
+ }
+
+void CEikDateEditor::SetDateFromCalendarAndDrawNow(const TTime& aDate)
+ {
+ iDateEditor->SetDate(aDate, *Font());
+ DrawNow();
+ }
+
+void CEikDateEditor::DoSetMinimumAndMaximum(const TTime& aMinimumDate, const TTime& aMaximumDate)
+ {
+ __ASSERT_ALWAYS(aMinimumDate<=aMaximumDate, Panic(EEikPanicDateEditorBadMinimumAndMaximum2));
+ TDateTime minimumDate=aMinimumDate.DateTime();
+ TDateTime maximumDate=aMaximumDate.DateTime();
+ iMinimumDate=TDateTime(minimumDate.Year(), minimumDate.Month(), minimumDate.Day(), 0, 0, 0, 0);
+ iMaximumDate=TDateTime(maximumDate.Year(), maximumDate.Month(), maximumDate.Day(), 0, 0, 0, 0);
+ TTime date=Date();
+ if (date<iMinimumDate)
+ SetDate(iMinimumDate);
+ else if (date>iMaximumDate)
+ SetDate(iMaximumDate);
+ }
+
+EXPORT_C void CEikDateEditor::CEikMfne_Reserved()
+ {
+ }
+
+EXPORT_C void CEikDateEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikTTimeEditor::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikDateEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikDateEditor::SetUninitialised(TBool aUninitialised)
+ {
+ iDateEditor->SetUninitialised(aUninitialised);
+ }
+
+EXPORT_C TBool CEikDateEditor::IsUninitialised() const
+ {
+ return iDateEditor->IsUninitialised();
+ }
+
+
+// CEikTimeAndDateEditor
+
+EXPORT_C CEikTimeAndDateEditor::CEikTimeAndDateEditor()
+ {
+ __DECLARE_NAME(_S("CEikTimeAndDateEditor"));
+ AKNTASHOOK_ADD( this, "CEikTimeAndDateEditor" );
+ }
+
+EXPORT_C CEikTimeAndDateEditor::~CEikTimeAndDateEditor()
+ {
+ AKNTASHOOK_REMOVE();
+ delete iTimeEditor;
+ delete iDateEditor;
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::ConstructL(const TTime& aMinimumTimeAndDate, const TTime& aMaximumTimeAndDate,
+ const TTime& aInitialTimeAndDate,TUint32 aFlags, HBufC* aInterveningText)
+ {
+ iTimeEditor=new(ELeave) CTimeEditor;
+ TInt numTimeFields(iTimeEditor->NumFieldsRequired(aFlags));
+ iDateEditor=new(ELeave) CDateEditor(*this,this,numTimeFields);
+ CreateFieldArrayL(numTimeFields+(aInterveningText? 1: 0)+iDateEditor->NumFieldsRequired());
+ const CFont& font=*Font();
+ CEikMfneSeparator* interveningText=NULL;
+
+ // Implement reversed time and date date for A&H locales
+ if ( TBidiText::ScriptDirectionality( (TLanguage)(User::Language() & KAknLanguageMask) ) == TBidiText::ELeftToRight)
+ {
+ iTimeEditor->ConstructFieldsL(*this, aInitialTimeAndDate, font);
+ iTimeEditor->RefreshFromLocale(font);
+
+ if (aInterveningText)
+ {
+ interveningText=CEikMfneSeparator::NewL(NULL);
+ AddField(interveningText);
+ }
+ iDateEditor->ConstructFieldsL(aMinimumTimeAndDate.DateTime().Year(), aMaximumTimeAndDate.DateTime().Year(), aInitialTimeAndDate, (aFlags&CTimeEditor::EWithoutPopoutCalendar), *iEikonEnv, font);
+ iDateEditor->RefreshFromLocale(font);
+ }
+ else // These are reversed
+ {
+ iDateEditor->ConstructFieldsL(aMinimumTimeAndDate.DateTime().Year(), aMaximumTimeAndDate.DateTime().Year(), aInitialTimeAndDate, (aFlags&CTimeEditor::EWithoutPopoutCalendar), *iEikonEnv, font);
+ iDateEditor->RefreshFromLocale(font);
+
+ if (aInterveningText)
+ {
+ interveningText=CEikMfneSeparator::NewL(NULL);
+ AddField(interveningText);
+ }
+
+ iTimeEditor->ConstructFieldsL(*this, aInitialTimeAndDate, font);
+ iTimeEditor->RefreshFromLocale(font);
+ }
+
+ DoSetMinimumAndMaximum(aMinimumTimeAndDate, aMaximumTimeAndDate);
+ // do stuff that can only be done when all leaving functions have successfully been done
+ if (aInterveningText)
+ interveningText->SetText(aInterveningText);
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::SetMinimumAndMaximum(const TTime& aMinimumTimeAndDate, const TTime& aMaximumTimeAndDate)
+ {
+ // __ASSERT_ALWAYS((aMinimumTimeAndDate>=iMinimumTimeAndDate) && (aMaximumTimeAndDate<=iMaximumTimeAndDate), Panic(EEikPanicTimeAndDateEditorBadMinimumAndMaximum1));
+ iDateEditor->SetMinimumAndMaximum(aMinimumTimeAndDate.DateTime().Year(), aMaximumTimeAndDate.DateTime().Year(), *Font());
+ DoSetMinimumAndMaximum(aMinimumTimeAndDate, aMaximumTimeAndDate);
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::GetMinimumAndMaximum(TTime& aMinimumTimeAndDate, TTime& aMaximumTimeAndDate) const
+ {
+ aMinimumTimeAndDate=iMinimumTimeAndDate;
+ aMaximumTimeAndDate=iMaximumTimeAndDate;
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::SetTimeAndDate(const TTime& aTimeAndDate)
+ {
+ const CFont& font=*Font();
+ iDateEditor->SetDate(aTimeAndDate, font);
+ TDateTime dateTime=aTimeAndDate.DateTime();
+ dateTime.SetYear(0);
+ dateTime.SetMonth(EJanuary);
+ dateTime.SetDay(0);
+ TTime timeWithoutDate(dateTime);
+ iTimeEditor->SetTime(timeWithoutDate, font);
+ }
+
+EXPORT_C TTime CEikTimeAndDateEditor::TimeAndDate() const
+ {
+ TTime time=iTimeEditor->Time();
+ return iDateEditor->Date(&time);
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::SetUninitialised(TBool aUninitialised)
+ {
+ iTimeEditor->SetUninitialised(aUninitialised);
+ iDateEditor->SetUninitialised(aUninitialised);
+ }
+
+EXPORT_C TBool CEikTimeAndDateEditor::IsUninitialised() const
+ {
+ return iTimeEditor->IsUninitialised() || iDateEditor->IsUninitialised();
+ }
+
+
+void CEikTimeAndDateEditor::SetTTime(const TTime& aTime)
+ {
+ SetTimeAndDate(aTime);
+ }
+
+TTime CEikTimeAndDateEditor::GetTTime() const
+ {
+ return(TimeAndDate());
+ }
+
+EXPORT_C TKeyResponse CEikTimeAndDateEditor::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
+ {
+ if (iDateEditor->OfferKeyEventL(aKeyEvent, aType)==EKeyWasConsumed)
+ return EKeyWasConsumed;
+ return CEikMfne::OfferKeyEventL(aKeyEvent, aType);
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TTime minimumTimeAndDate=ReadTimeAndDate(aResourceReader);
+ TTime maximumTimeAndDate=ReadTimeAndDate(aResourceReader);
+ TBool flags=aResourceReader.ReadUint8();
+ HBufC* interveningText=aResourceReader.ReadHBufCL();
+ CleanupStack::PushL(interveningText);
+ ConstructL(minimumTimeAndDate, maximumTimeAndDate, maximumTimeAndDate, flags, interveningText);
+ CleanupStack::Pop();
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::PrepareForFocusLossL()
+ {
+ CEikMfne::PrepareForFocusLossL();
+ iDateEditor->PrepareForFocusLossL();
+ TTime timeAndDate=TimeAndDate();
+ if (timeAndDate<iMinimumTimeAndDate)
+ {
+ SetTimeAndDate(iMinimumTimeAndDate);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_BEFORE_EARLIEST_ALLOWED_TIME_AND_DATE, iMinimumTimeAndDate);
+ }
+ else if (timeAndDate>iMaximumTimeAndDate)
+ {
+ SetTimeAndDate(iMaximumTimeAndDate);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_AFTER_LATEST_ALLOWED_TIME_AND_DATE, iMaximumTimeAndDate);
+ }
+ }
+
+void CEikTimeAndDateEditor::CreatePopoutIfRequiredL()
+ {
+ iDateEditor->CreatePopoutIfRequiredL();
+ }
+
+void CEikTimeAndDateEditor::GetMinimumAndMaximumAndInitialDatesForCalendarL(TTime& aMinimumDate, TTime& aMaximumDate, TTime& aInitialDate) const
+ {
+ aMinimumDate=iMinimumTimeAndDate;
+ aMaximumDate=iMaximumTimeAndDate;
+ TDateTime date;
+ if (iDateEditor->IsTextNull())
+ CEikMfne::LeaveWithAlert(R_EIK_TBUF_DATE_INVALID);
+ if (date.Set(iDateEditor->Year(), (TMonth)(iDateEditor->Month()-1), iDateEditor->Day()-1, 0, 0, 0, 0)!=KErrNone)
+ CEikMfne::LeaveWithAlert(R_EIK_TBUF_DATE_INVALID);
+ aInitialDate=iDateEditor->Date();
+ }
+
+void CEikTimeAndDateEditor::SetDateFromCalendarAndDrawNow(const TTime& aDate)
+ {
+ iDateEditor->SetDate(aDate, *Font());
+ DrawNow();
+ }
+
+void CEikTimeAndDateEditor::DoSetMinimumAndMaximum(const TTime& aMinimumTimeAndDate, const TTime& aMaximumTimeAndDate)
+ {
+ __ASSERT_ALWAYS(aMinimumTimeAndDate<=aMaximumTimeAndDate, Panic(EEikPanicTimeAndDateEditorBadMinimumAndMaximum2));
+ iMinimumTimeAndDate=aMinimumTimeAndDate;
+ iMaximumTimeAndDate=aMaximumTimeAndDate;
+ TTime timeAndDate=TimeAndDate();
+ if (timeAndDate<iMinimumTimeAndDate)
+ SetTimeAndDate(iMinimumTimeAndDate);
+ else if (timeAndDate>iMaximumTimeAndDate)
+ SetTimeAndDate(iMaximumTimeAndDate);
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikTTimeEditor::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikTimeAndDateEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikTimeAndDateEditor::CEikMfne_Reserved()
+ {
+ }
+
+
+// CEikDurationEditor
+
+EXPORT_C CEikDurationEditor::CEikDurationEditor()
+ {
+ __DECLARE_NAME(_S("CEikDurationEditor"));
+ AKNTASHOOK_ADD( this, "CEikDurationEditor" );
+ }
+
+EXPORT_C CEikDurationEditor::~CEikDurationEditor()
+ {
+ AKNTASHOOK_REMOVE();
+ delete iTimeEditor;
+ }
+
+EXPORT_C void CEikDurationEditor::ConstructL(const TTimeIntervalSeconds& aMinimumDuration, const TTimeIntervalSeconds& aMaximumDuration, const TTimeIntervalSeconds& aInitialDuration, TUint32 aFlags)
+ {
+ iTimeEditor=new(ELeave) CTimeEditor;
+ aFlags|=CTimeEditor::EForce24HourFormat;
+ CreateFieldArrayL(iTimeEditor->NumFieldsRequired(aFlags));
+ iTimeEditor->ConstructFieldsL(*this, Convert(aInitialDuration), *Font());
+ iTimeEditor->RefreshFromLocale(*Font());
+
+ DoSetMinimumAndMaximum(aMinimumDuration, aMaximumDuration);
+ }
+
+EXPORT_C void CEikDurationEditor::SetMinimumAndMaximum(const TTimeIntervalSeconds& aMinimumDuration, const TTimeIntervalSeconds& aMaximumDuration)
+ {
+ // __ASSERT_ALWAYS((aMinimumDuration>=iMinimumDuration) && (aMaximumDuration<=iMaximumDuration), Panic(EEikPanicDurationEditorBadMinimumAndMaximum1));
+ DoSetMinimumAndMaximum(aMinimumDuration, aMaximumDuration);
+ }
+
+EXPORT_C void CEikDurationEditor::GetMinimumAndMaximum(TTimeIntervalSeconds& aMinimumDuration, TTimeIntervalSeconds& aMaximumDuration) const
+ {
+ aMinimumDuration=iMinimumDuration;
+ aMaximumDuration=iMaximumDuration;
+ }
+
+EXPORT_C void CEikDurationEditor::SetDuration(const TTimeIntervalSeconds& aDuration)
+ {
+ iTimeEditor->SetTime(Convert(aDuration), *Font());
+ }
+
+EXPORT_C TTimeIntervalSeconds CEikDurationEditor::Duration() const
+ {
+ return Convert(iTimeEditor->Time());
+ }
+
+EXPORT_C void CEikDurationEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TTimeIntervalSeconds minimumDuration=ReadDuration(aResourceReader);
+ TTimeIntervalSeconds maximumDuration=ReadDuration(aResourceReader);
+ TUint32 flags=aResourceReader.ReadUint8();
+ ConstructL(minimumDuration, maximumDuration, maximumDuration, flags);
+ }
+
+EXPORT_C void CEikDurationEditor::PrepareForFocusLossL()
+ {
+ CEikMfne::PrepareForFocusLossL();
+ TTimeIntervalSeconds duration=Duration();
+ if (duration<iMinimumDuration)
+ {
+ SetDuration(iMinimumDuration);
+
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_BELOW_SHORTEST_ALLOWED_DURATION, Convert(iMinimumDuration));
+ }
+ else if (duration>iMaximumDuration)
+ {
+ SetDuration(iMaximumDuration);
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(R_EIK_TBUF_ABOVE_LONGEST_ALLOWED_DURATION, Convert(iMaximumDuration));
+ }
+ }
+
+void CEikDurationEditor::DoSetMinimumAndMaximum(const TTimeIntervalSeconds& aMinimumDuration, const TTimeIntervalSeconds& aMaximumDuration)
+ {
+ __ASSERT_ALWAYS(aMinimumDuration<=aMaximumDuration, Panic(EEikPanicDurationEditorBadMinimumAndMaximum2));
+ iMinimumDuration=aMinimumDuration;
+ iMaximumDuration=aMaximumDuration;
+ TTimeIntervalSeconds duration=Duration();
+ if (duration<iMinimumDuration)
+ SetDuration(iMinimumDuration);
+ else if (duration>iMaximumDuration)
+ SetDuration(iMaximumDuration);
+ }
+
+EXPORT_C void CEikDurationEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikMfne::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikDurationEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikDurationEditor::CEikMfne_Reserved()
+ {
+ }
+
+
+// CEikTimeOffsetEditor
+
+EXPORT_C CEikTimeOffsetEditor::CEikTimeOffsetEditor()
+ {
+ __DECLARE_NAME(_S("CEikTimeOffsetEditor"));
+ AKNTASHOOK_ADD( this, "CEikTimeOffsetEditor" );
+ }
+
+EXPORT_C CEikTimeOffsetEditor::~CEikTimeOffsetEditor()
+ {
+ AKNTASHOOK_REMOVE();
+ delete iTimeEditor;
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::ConstructL(const TTimeIntervalSeconds& aMinimumTimeOffset, const TTimeIntervalSeconds& aMaximumTimeOffset, const TTimeIntervalSeconds& aInitialTimeOffset, TUint32 aFlags)
+ {
+ TTimeIntervalSeconds magnitudeOfInitialTimeOffset=aInitialTimeOffset;
+ TBool positive=ETrue;
+ if (magnitudeOfInitialTimeOffset.Int()<0)
+ {
+ magnitudeOfInitialTimeOffset=-magnitudeOfInitialTimeOffset.Int();
+ positive=EFalse;
+ }
+ iTimeEditor=new(ELeave) CTimeEditor;
+ if (~aFlags&CTimeEditor::ETimeZoneOffsetFormat)
+ {
+ aFlags|=CTimeEditor::EForce24HourFormat;
+ }
+ CreateFieldArrayL(2+iTimeEditor->NumFieldsRequired(aFlags));
+ iSign=CEikMfneSymbol::NewL(2);
+ CleanupStack::PushL(iSign); // this needs to be pushed as it would not be destroyed by the class' destructor
+ // add the "+" symbol
+ HBufC* plusText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ *plusText=KPlus;
+ iSign->AddSymbolicItem(CEikMfneSymbol::CItem::NewL('+', '+', plusText), positive);
+ CleanupStack::Pop();
+ // add the "-" symbol
+ HBufC* minusText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ *minusText=KMinus;
+ iSign->AddSymbolicItem(CEikMfneSymbol::CItem::NewL('-', '-', minusText), !positive);
+ CleanupStack::Pop(2);
+ AddField(iSign);
+ HBufC* spaceSeparatorText=HBufC::NewLC(1); // also pushes on to CleanupStack
+ spaceSeparatorText->Des().Append(TChar(' '));
+ AddField(CEikMfneSeparator::NewL(spaceSeparatorText));
+ CleanupStack::Pop();
+ iTimeEditor->ConstructFieldsL(*this, Convert(magnitudeOfInitialTimeOffset), *Font());
+ DoSetMinimumAndMaximum(aMinimumTimeOffset, aMaximumTimeOffset);
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::SetMinimumAndMaximum(const TTimeIntervalSeconds& aMinimumTimeOffset, const TTimeIntervalSeconds& aMaximumTimeOffset)
+ {
+ // __ASSERT_ALWAYS((aMinimumTimeOffset>=iMinimumTimeOffset) && (aMaximumTimeOffset<=iMaximumTimeOffset), Panic(EEikPanicTimeOffsetEditorBadMinimumAndMaximum1));
+ DoSetMinimumAndMaximum(aMinimumTimeOffset, aMaximumTimeOffset);
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::GetMinimumAndMaximum(TTimeIntervalSeconds& aMinimumTimeOffset, TTimeIntervalSeconds& aMaximumTimeOffset) const
+ {
+ aMinimumTimeOffset=iMinimumTimeOffset;
+ aMaximumTimeOffset=iMaximumTimeOffset;
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::SetTimeOffset(const TTimeIntervalSeconds& aTimeOffset)
+ {
+ TTimeIntervalSeconds magnitudeOfTimeOffset=aTimeOffset;
+ TInt signId='+';
+ if (magnitudeOfTimeOffset.Int()<0)
+ {
+ magnitudeOfTimeOffset=-magnitudeOfTimeOffset.Int();
+ signId='-';
+ }
+ iTimeEditor->SetTime(Convert(magnitudeOfTimeOffset), *Font());
+ iSign->SetCurrentSymbolicItemToId(signId);
+ }
+
+EXPORT_C TTimeIntervalSeconds CEikTimeOffsetEditor::TimeOffset() const
+ {
+ TTimeIntervalSeconds timeOffset=Convert(iTimeEditor->Time());
+ if (iSign->IdOfCurrentSymbolicItem()=='-')
+ timeOffset=-timeOffset.Int();
+ return timeOffset;
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::ConstructFromResourceL(TResourceReader& aResourceReader)
+ {
+ TTimeIntervalSeconds minimumTimeOffset=ReadTimeOffset(aResourceReader);
+ TTimeIntervalSeconds maximumTimeOffset=ReadTimeOffset(aResourceReader);
+ TUint32 flags=aResourceReader.ReadUint8();
+ ConstructL(minimumTimeOffset, maximumTimeOffset, maximumTimeOffset, flags);
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::PrepareForFocusLossL()
+ {
+ CEikMfne::PrepareForFocusLossL();
+ TTimeIntervalSeconds timeOffset=TimeOffset();
+ if (timeOffset<iMinimumTimeOffset)
+ {
+ SetTimeOffset(iMinimumTimeOffset);
+ TInt valueOfMinimumTimeOffset=iMinimumTimeOffset.Int();
+ TInt resourceId=R_EIK_TBUF_BELOW_MINIMUM_TIME_OFFSET;
+ if (valueOfMinimumTimeOffset<0)
+ {
+ valueOfMinimumTimeOffset=-valueOfMinimumTimeOffset;
+ resourceId=R_EIK_TBUF_BELOW_NEGATIVE_MINIMUM_TIME_OFFSET;
+ }
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(resourceId, Convert(TTimeIntervalSeconds(valueOfMinimumTimeOffset)));
+ }
+ else if (timeOffset>iMaximumTimeOffset)
+ {
+ SetTimeOffset(iMaximumTimeOffset);
+ TInt valueOfMaximumTimeOffset=iMaximumTimeOffset.Int();
+ TInt resourceId=R_EIK_TBUF_ABOVE_MAXIMUM_TIME_OFFSET;
+ if (valueOfMaximumTimeOffset<0)
+ {
+ valueOfMaximumTimeOffset=-valueOfMaximumTimeOffset;
+ resourceId=R_EIK_TBUF_ABOVE_NEGATIVE_MAXIMUM_TIME_OFFSET;
+ }
+ DrawNowAndLeaveWithTimeDateFormatInfoMsgL(resourceId, Convert(TTimeIntervalSeconds(valueOfMaximumTimeOffset)));
+ }
+ }
+
+void CEikTimeOffsetEditor::DoSetMinimumAndMaximum(const TTimeIntervalSeconds& aMinimumTimeOffset, const TTimeIntervalSeconds& aMaximumTimeOffset)
+ {
+ __ASSERT_ALWAYS(aMinimumTimeOffset<=aMaximumTimeOffset, Panic(EEikPanicTimeOffsetEditorBadMinimumAndMaximum2));
+ iMinimumTimeOffset=aMinimumTimeOffset;
+ iMaximumTimeOffset=aMaximumTimeOffset;
+ TTimeIntervalSeconds timeOffset=TimeOffset();
+ if (timeOffset<iMinimumTimeOffset)
+ SetTimeOffset(iMinimumTimeOffset);
+ else if (timeOffset>iMaximumTimeOffset)
+ SetTimeOffset(iMaximumTimeOffset);
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+ {
+ CEikMfne::HandlePointerEventL(aPointerEvent);
+ }
+
+EXPORT_C void* CEikTimeOffsetEditor::ExtensionInterface( TUid /*aInterface*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void CEikTimeOffsetEditor::CEikMfne_Reserved()
+ {
+ }
+
+EXPORT_C void CEikMfne::SetSkinTextColorL(TInt aAknSkinIDForTextColor, TInt aAknSkinIDForBgColor)
+ {
+ CreateExtensionIfRequiredL();
+
+ iExtension->iAknSkinColorIndex = aAknSkinIDForTextColor;
+ iExtension->iSkinIdForTextBackgroundColor = aAknSkinIDForBgColor;
+
+ // if we are already visible, try to apply new color
+ if (IsVisible())
+ {
+ DrawDeferred(); // No hurry anyway
+ }
+ }
+
+EXPORT_C void CEikMfne::SizeChanged()
+ {
+ CEikBorderedControl::SizeChanged();
+ if ( !iFields || iCurrentField < 0 || iCurrentField >= iNumFields )
+ {
+ return;
+ }
+ TBool cursorDisplay( iFields[iCurrentField]->HighlightType() ==
+ CEikMfneField::ECursor );
+ if ( IsFocused() && cursorDisplay )
+ {
+ TRect mainPaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane,
+ mainPaneRect );
+ TRect rect( Rect() );
+ if ( rect.iTl.iY < 0 || rect.iBr.iY > mainPaneRect.Height() ||
+ rect.iTl.iX >= mainPaneRect.Width() || rect.iBr.iX <= 0 )
+ {
+ HideCursor();
+ }
+ else
+ {
+ DrawCursor();
+ }
+ }
+ }
+
+EXPORT_C void CEikMfne::MakeVisible( TBool aVisible )
+ {
+ CEikBorderedControl::MakeVisible( aVisible );
+ if ( !aVisible && iExtension->iCursorShown )
+ {
+ HideCursor();
+ }
+ }
+
+void CEikMfne::SetValidateCallBack( TCallBack aCallBack )
+ {
+ if ( iExtension )
+ {
+ iExtension->iValidateValueCallBack = aCallBack;
+ }
+ }
+
+void CEikMfne::ReportStateChangeEventL()
+ {
+ ReportEventL( MCoeControlObserver::EEventStateChanged );
+ }
+
+void CEikMfne::LaunchPenInputL()
+ {
+ if ( iExtension && !iExtension->iDisablePenInput )
+ {
+ if ( iExtension->iFingerSupport &&
+ iExtension->iFingerParam == EnableWithAllHighlight )
+ {
+ iExtension->iHighlightAll = !iExtension->iTouchActivated &&
+ !(iExtension->iExtendedInputCapabilities->Capabilities() & CAknExtendedInputCapabilities::EInputEditorQwertyInputActive);
+ if ( iExtension->iHighlightAll )
+ {
+ SetFirstEditableField();
+ }
+ ReportUpdate();
+ DrawDeferred();
+ }
+ iExtension->iExtendedInputCapabilities->ReportEventL(
+ CAknExtendedInputCapabilities::MAknEventObserver::EActivatePenInputRequest,
+ 0 );
+ iExtension->iTouchActivated = ETrue;
+ }
+ }