--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/landmarksui/uicontrols/src/CLmkDecimalEditor.cpp Wed Sep 01 12:31:27 2010 +0100
@@ -0,0 +1,703 @@
+/*
+* Copyright (c) 2005 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: LandmarksUi Content File -
+*
+*/
+
+
+
+
+
+
+
+
+// INCLUDE FILES
+#include <barsread.h>
+#include <eikenv.h>
+#include <NumberConversion.h>
+#include <AknUtils.h>
+#include <aknsoundsystem.h>
+#include <AknAppUi.h>
+#include <AknTextDecorationMetrics.h>
+#include <eikctl.rsg>
+#include <e32math.h>
+
+#include "CLmkDecimalEditor.h"
+
+
+_LIT(KMinus,"-");
+
+namespace EUtils
+ {
+ LOCAL_D TBool IsAnyDigit(TChar aCharacter)
+ {
+ return ( aCharacter.GetNumericValue() != KErrNotFound);
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::CLmkDecimalEditor
+// ---------------------------------------------------------
+//
+CLmkDecimalEditor::CLmkDecimalEditor(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();
+ iEnv = CEikonEnv::Static();
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::~CLmkDecimalEditor
+// ---------------------------------------------------------
+//
+CLmkDecimalEditor::~CLmkDecimalEditor()
+ {
+ delete iText;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::NewL
+// ---------------------------------------------------------
+//
+CLmkDecimalEditor* CLmkDecimalEditor::NewL(const CFont& aFont, TResourceReader& aResourceReader)
+ {
+ TInt minimumValue=aResourceReader.ReadInt32();
+ TInt maximumValue=aResourceReader.ReadInt32();
+ TUint32 flags=aResourceReader.ReadUint8();
+ return NewL(aFont, minimumValue, maximumValue, maximumValue, flags, 0);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::NewL
+// ---------------------------------------------------------
+//
+CLmkDecimalEditor* CLmkDecimalEditor::NewL(const CFont& aFont, TInt aMinimumValue, TInt aMaximumValue, TInt aInitialValue, TUint32 aFlags, TInt aNumberOfZeros)
+ {
+ CLmkDecimalEditor* number=new(ELeave) CLmkDecimalEditor(aMinimumValue, aMaximumValue, aFlags);
+ CleanupStack::PushL(number);
+ number->iText=HBufC::NewL(number->MaximumNumberOfDigits()+((aMinimumValue<0)? 1: 0));
+ number->ConstructL(aNumberOfZeros);
+ number->SetValue(aInitialValue, aFont);
+ CleanupStack::Pop();
+ return number;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::InvalidFieldAlert
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::InvalidFieldAlert() const
+ {
+ CAknKeySoundSystem* soundPlayer = (static_cast<CAknAppUi*>(iEnv->AppUi()))->KeySounds();
+ if(soundPlayer)
+ {
+ soundPlayer->PlaySound(EAvkonSIDWarningTone);
+ }
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::AdditionalWidthForHighlights
+// ---------------------------------------------------------
+//
+TInt CLmkDecimalEditor::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;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::WidthInPixels
+// ---------------------------------------------------------
+//
+TInt CLmkDecimalEditor::WidthInPixels(const CFont& aFont) const
+ {
+ return Max( iMinimumWidthInPixels, aFont.TextWidthInPixels(Text()) + AdditionalWidthForHighlights(aFont) );
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::ConstructL
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::ConstructL(TInt aNumberOfZeros)
+ {
+ iNudgeCharMinus=iEnv->NudgeCharMinus();
+ iNudgeCharPlus=iEnv->NudgeCharPlus();
+ iNumberOfZeros = aNumberOfZeros;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::SetMinimumAndMaximum
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::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();
+ iMinimumValue=aMinimumValue;
+ iMaximumValue=aMaximumValue;
+ TInt value=ValueFromText();
+ if (value<aMinimumValue||!NumberOfDigits())
+ SetTextToValue(aMinimumValue, aFont);
+ else if (value>aMaximumValue)
+ SetTextToValue(aMaximumValue, aFont);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::GetMinimumAndMaximum
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::GetMinimumAndMaximum(TInt& aMinimumValue, TInt& aMaximumValue) const
+ {
+ aMinimumValue=iMinimumValue;
+ aMaximumValue=iMaximumValue;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::SetValue
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::SetValue(TInt aValue, const CFont& aFont)
+ {
+ SetTextToValue(aValue, aFont);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::Value
+// ---------------------------------------------------------
+//
+TReal CLmkDecimalEditor::Value() const
+ {
+ TInt numberOfDigits = NumberOfDigits();
+ TReal retVal(0);
+ TReal temp(0);
+
+ if (numberOfDigits == 0)
+ {
+ InvalidFieldAlert();
+ }
+
+ TInt value = ValueFromText();
+ if (value < iMinimumValue)
+ {
+ InvalidFieldAlert();
+ iEnv->LeaveWithInfoMsg(R_EIK_TBUF_NUMBER_BELOW_MIN, iMinimumValue);
+ }
+ if (value > iMaximumValue)
+ {
+ iEnv->LeaveWithInfoMsg(R_EIK_TBUF_NUMBER_ABOVE_MAX, iMaximumValue);
+ }
+ Math::Pow10(temp, numberOfDigits * (-1));
+ retVal = value * temp;
+ return retVal;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::IsValid
+// ---------------------------------------------------------
+//
+TBool CLmkDecimalEditor::IsValid() const
+ {
+ return (NumberOfDigits() != 0);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::NormalizeDigit
+// ---------------------------------------------------------
+//
+TChar CLmkDecimalEditor::NormalizeDigit(TChar aChar)
+ {
+ TBuf<1> buf;
+ buf.Append(aChar);
+ NumberConversion::ConvertDigits(buf, iDigitType);
+ return buf[0];
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::ZeroCharacter
+// ---------------------------------------------------------
+//
+TText CLmkDecimalEditor::ZeroCharacter() const
+ {
+ return TText(iDigitType);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::NegativeCharacter
+// ---------------------------------------------------------
+//
+TText CLmkDecimalEditor::NegativeCharacter() const
+ {
+ return TText('-');
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::IsTextNull
+// ---------------------------------------------------------
+//
+TBool CLmkDecimalEditor::IsTextNull() const
+ {
+ return ( Text().Length() < 1 );
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::MaximumWidthInPixels
+// ---------------------------------------------------------
+//
+TInt CLmkDecimalEditor::MaximumWidthInPixels(const CFont& aFont, TBool aShrinkToMinimumSize)
+ {
+ if (aShrinkToMinimumSize)
+ {
+ 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)*/;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::InputCapabilities
+// ---------------------------------------------------------
+//
+TCoeInputCapabilities CLmkDecimalEditor::InputCapabilities() const
+ {
+ TUint inputCapabilities=TCoeInputCapabilities::ENone;
+ if (iMinimumValue<0)
+ {
+ inputCapabilities|=TCoeInputCapabilities::EWesternNumericIntegerNegative;
+ }
+ if (iMaximumValue>0)
+ {
+ inputCapabilities|=TCoeInputCapabilities::EWesternNumericIntegerPositive;
+ }
+ return TCoeInputCapabilities(inputCapabilities);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::Text
+// ---------------------------------------------------------
+//
+const TDesC& CLmkDecimalEditor::Text() const
+ {
+ if (IsUninitialised())
+ return KNullDesC();
+ else
+ return *iText;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::IsEditable
+// ---------------------------------------------------------
+//
+TBool CLmkDecimalEditor::IsEditable() const
+ {
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::HighlightType
+// ---------------------------------------------------------
+//
+CEikMfneField::THighlightType CLmkDecimalEditor::HighlightType() const
+ {
+ return (iFlags&EIsBeingEditedWithCursor)? ECursor: EInverseVideo;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::HandleKey
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::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
+ {
+ doAdjust:
+ const TInt nudge=(nudgeTen? 10 : 1);
+ TInt newValue;
+
+
+ if ((textLength==0) || ! EUtils::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) || ! EUtils::IsAnyDigit( TChar(text[textLength-1])) )
+ newValue=0;
+ else
+ newValue=ValueFromText()+((ch==EKeyDownArrow)? -nudge: nudge);
+
+ if (newValue>iMaximumValue)
+ newValue=iMinimumValue;
+ else if (newValue<iMinimumValue)
+ newValue=iMaximumValue;
+ SetTextToValue(newValue, aFont);
+ aHighlightIncrement=0;// Always highlight the field being nudged
+ aDataAltered=ETrue;
+ iFlags&=~EIsBeingEditedWithCursor;
+ }
+ aDataAltered=ETrue;
+ }
+ break;
+ case EKeyBackspace:
+ if (textLength)
+ {
+ iFlags|=EIsBeingEditedWithCursor;
+ text.SetLength(textLength-1);
+ if (text==KMinus)
+ text.SetLength(0);
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+ }
+ break;
+ case '+':
+ break;
+ case '-':
+ if (iMinimumValue < 0)
+ {
+ if (~iFlags&EIsBeingEditedWithCursor)
+ {
+ iFlags|=EIsBeingEditedWithCursor;
+ text.SetLength(0);
+ }
+ if (text.Length()==0)
+ {
+ text.Append('-');
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+ }
+ }
+ break;
+ default:
+ TBuf<2> nudgeTenChars;
+ CCoeEnv::Static()->ReadResource(nudgeTenChars,R_EIK_TBUF_NUDGE_TEN_CHARS);
+
+ if ( EUtils::IsAnyDigit(ch) )
+ {
+ if (~iFlags&EIsBeingEditedWithCursor)
+ {
+ iFlags|=EIsBeingEditedWithCursor;
+ text.SetLength(0);
+ }
+ text.Append(NormalizeDigit(ch) );
+ aDataAltered=ETrue;
+ SetUninitialised(EFalse);
+ if (NumberOfDigits()>=MaximumNumberOfDigits())
+ aHighlightIncrement=1;
+ }
+ if (ch==iNudgeCharMinus)
+ {
+ ch=EKeyLeftArrow;
+ goto doAdjust;
+ }
+ else if (ch==iNudgeCharPlus)
+ {
+ ch=EKeyRightArrow;
+ goto doAdjust;
+ }
+ else if (ch==((TUint)nudgeTenChars[0]))
+ {
+ ch=EKeyLeftArrow;
+ nudgeTen=ETrue;
+ goto doAdjust;
+ }
+ else if (ch==((TUint)nudgeTenChars[1]))
+ {
+ ch=EKeyRightArrow;
+ nudgeTen=ETrue;
+ goto doAdjust;
+ }
+ break;
+ }
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::HandleDeHighlight
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::HandleDeHighlight(const CFont& aFont, CEikonEnv& aEikonEnv, TBool& aDataAltered, TBool& aError)
+ {
+ iFlags&=~EIsBeingEditedWithCursor;
+ if (NumberOfDigits()==0)
+ {
+ SetTextToValue(iMaximumValue, aFont);
+ aDataAltered=ETrue;
+ aError=ETrue;
+ aEikonEnv.InfoMsg(R_EIK_TBUF_NO_NUMBER_ENTERED);
+ return;
+ }
+ TInt value=ValueFromText();
+ if ((value<iMinimumValue) || (value>iMaximumValue))
+ {
+ TBool succeeded = ConvertsIntoValidValue(value);
+ if ( !succeeded )
+ {
+ aDataAltered=ETrue;
+ aError=ETrue;
+ if (value<iMinimumValue)
+ {
+ SetTextToValue(iMinimumValue, aFont);
+ InvalidFieldAlert();
+ aEikonEnv.InfoMsg(R_EIK_TBUF_NUMBER_BELOW_MIN, iMinimumValue);
+ return;
+ }
+ if (value>iMaximumValue)
+ {
+ 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);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::MaximumNumberOfDigits
+// ---------------------------------------------------------
+//
+TInt CLmkDecimalEditor::MaximumNumberOfDigits() const
+ {
+ return Max(2,iMaxDigits);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::NumberOfDigits
+// ---------------------------------------------------------
+//
+TInt CLmkDecimalEditor::NumberOfDigits() const
+ {
+ return iText->Length();
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::SetTextToValue
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::SetTextToValue(TInt aValue, const CFont& aFont)
+ {
+ SetUninitialised(EFalse);
+ TPtr text=iText->Des();
+ text.SetLength(0);
+ if (aValue<0)
+ {
+ text.Append('-');
+ aValue=-aValue;
+ }
+ TInt firstUnsetCharacter=text.Length();
+ text.SetLength(firstUnsetCharacter+MaximumNumberOfDigits());
+ TInt lastUnsetCharacter=text.Length()-1;
+ if (aValue==0)
+ text[lastUnsetCharacter--]=ZeroCharacter();
+ else
+ {
+ for (; aValue; aValue/=10)
+ text[lastUnsetCharacter--]=(TText)(ZeroCharacter()+(aValue%10));
+ }
+ while(iNumberOfZeros--)
+ {
+ text[lastUnsetCharacter--]=(TText)(ZeroCharacter());
+ }
+ iNumberOfZeros = 0;
+
+ if (lastUnsetCharacter>=firstUnsetCharacter)
+ {
+ if (iFlags&EFillWithLeadingZeros)
+ while (lastUnsetCharacter>=firstUnsetCharacter) text[lastUnsetCharacter--]=ZeroCharacter();
+ else
+ text.Delete(firstUnsetCharacter, (lastUnsetCharacter+1)-firstUnsetCharacter);
+ }
+ if (iFlags&EPreserveOldWidthBeforeEditing)
+ iMinimumWidthInPixels = WidthInPixels(aFont);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::ValueFromText
+// ---------------------------------------------------------
+//
+TInt CLmkDecimalEditor::ValueFromText() const
+ {
+ if (!NumberOfDigits())
+ return iMinimumValue;
+ TInt i=0;
+ TInt valueFromText=0;
+ TBool isNegative=EFalse;
+ switch ((*iText)[i])
+ {
+ case '-':
+ ++i;
+ isNegative=ETrue;
+ break;
+ }
+ TInt textLength=iText->Length();
+ for (; i<textLength; ++i)
+ {
+ TText digit=(*iText)[i];
+ if (i>=textLength-2)
+ {
+ if (!isNegative && valueFromText>(KMaxTInt32/10))
+ return KMaxTInt32;
+ else if (isNegative && (-valueFromText)<(KMinTInt32/10))
+ return KMinTInt32;
+ }
+ valueFromText=(valueFromText*10)+(TInt)(digit-ZeroCharacter());
+ }
+ if (isNegative==EFalse && valueFromText<0)
+ return KMaxTInt32;// Deals with overflow
+ if (isNegative)
+ valueFromText=-valueFromText;
+ return valueFromText;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::ConvertsIntoValidValue
+// ---------------------------------------------------------
+//
+TBool CLmkDecimalEditor::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;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::SetUninitialised
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::SetUninitialised(TBool aUninitialised)
+ {
+ if (aUninitialised)
+ iFlags |= EIsUninitialised;
+ else
+ iFlags &= ~EIsUninitialised;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::IsUninitialised
+// ---------------------------------------------------------
+//
+TBool CLmkDecimalEditor::IsUninitialised() const
+ {
+ return iFlags & EIsUninitialised;
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::RefreshDigitType
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::RefreshDigitType( const CFont& aFont)
+ {
+ SetDigitType( AknTextUtils::NumericEditorDigitType(), aFont);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::SetDigitType
+// ---------------------------------------------------------
+//
+void CLmkDecimalEditor::SetDigitType(TDigitType aDigitType, const CFont& aFont)
+ {
+ TInt value = Value();
+ iDigitType = aDigitType;
+ SetTextToValue(value, aFont);
+ }
+
+// ---------------------------------------------------------
+// CLmkDecimalEditor::DigitType
+// ---------------------------------------------------------
+//
+TDigitType CLmkDecimalEditor::DigitType() const
+ {
+ return iDigitType;
+ }
+