diff -r 000000000000 -r 2f259fa3e83a uifw/eikctl/src/EIKMFNE.CPP --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Skins drawing support +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// 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 (valueaMaximumValue) + 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= 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 ((valueiMaximumValue)) + { + TBool succeeded = ConvertsIntoValidValue(value); + if ( !succeeded ) + { + aDataAltered=ETrue; + aError=ETrue; + if (valueiMaximumValue) + { + 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-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; iAddSymbolicItem(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; iiSymbolicItems[i]=NULL; + CleanupStack::Pop(); + return symbol; + } + +EXPORT_C void CEikMfneSymbol::AddSymbolicItem(CItem* aSymbolicItem, TBool aMakeCurrent) + { + __ASSERT_DEBUG(iSymbolicItems, Panic(EEikPanicMfneSymbolicItemArrayNotCreated)); + for (TInt i=0; iiId==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; iiText); + if (maximumWidthInPixelsiKeyToMatch; + if ((keyToMatchTCharF('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; i0, Panic(EEikPanicMfneTooFewFields)); + iNumFields=aNumFields; + iFields=new(ELeave) CEikMfneField*[aNumFields]; + for (TInt i=0; iIsEditable()) + 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(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; iInputCapabilities()); + } + + //inputCapabilities.SetObjectProvider(const_cast(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) && ((iCurrentFieldlastFieldToDraw))) + { + __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; iMaximumWidthInPixels(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; iWidthInPixels(font); + if (iFields[i]->IsEditable()) + { + TInt rightPositionOfThisField=(leftPositionOfThisField+widthOfThisFieldInPixels)-1; + if (rightPositionOfThisFieldiFeedback->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;iWidthInPixels(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; iWidthInPixels( 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& 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()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=0) && (aPositioniDateElements[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( 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 (timeiMaximumTime) + { + 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 (timeiMaximumTime) + 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 (dateiMaximumDate) + { + 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 (dateiMaximumDate) + 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 (timeAndDateiMaximumTimeAndDate) + { + 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 (timeAndDateiMaximumTimeAndDate) + 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 (durationiMaximumDuration) + { + 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 (durationiMaximumDuration) + 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 (timeOffsetiMaximumTimeOffset) + { + 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 (timeOffsetiMaximumTimeOffset) + 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; + } + }