--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/landmarksui/uicontrols/src/CLmkMfneFloat.cpp Tue Feb 02 00:16:03 2010 +0200
@@ -0,0 +1,580 @@
+/*
+* 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 <e32math.h>
+#include "CLmkMfneFloat.h"
+#include <aknutils.h>
+
+namespace {
+
+const TInt KNumOtherSymbols = 2; // +/- and decimal point
+
+_LIT(KMinus,"-");
+
+const TInt KEventCodeStarSign(42);
+const TInt KEventCodeMinusSign(45);
+const TInt KKeyToMatchPoint = 35; // Shift/Hash
+const TInt KPointKeyFromQwerty = 46;
+
+#if defined(_DEBUG)
+void Panic(TInt aReason)
+ {
+ _LIT(KPanicCategory, "LMK_MFNE_FLT");
+ User::Panic(KPanicCategory, aReason);
+ }
+#endif
+
+TReal Nan()
+ {
+ TRealX nan;
+ nan.SetNaN();
+ return nan;
+ }
+
+TBool IsAnyDigit(TChar aCharacter)
+ {
+ return (aCharacter.GetNumericValue() != KErrNotFound);
+ }
+
+void TrimRightmostChar(TDes& aText)
+ {
+ if (aText.Length())
+ {
+ aText.SetLength(aText.Length() - 1);
+ }
+ }
+}
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::CLmkMfneFloat
+// ---------------------------------------------------------
+//
+CLmkMfneFloat::CLmkMfneFloat(
+ TInt aMaxDigits,
+ TInt aMaxDecimalDigits)
+ :
+ iMaxDigits(aMaxDigits),
+ iMaxDecimalDigits(aMaxDecimalDigits)
+ {
+ __ASSERT_DEBUG(aMaxDigits > 0, Panic(KErrArgument));
+ __ASSERT_DEBUG(aMaxDecimalDigits > 0, Panic(KErrArgument));
+ __ASSERT_DEBUG(aMaxDecimalDigits <= aMaxDigits, Panic(KErrArgument));
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::~CLmkMfneFloat
+// ---------------------------------------------------------
+//
+CLmkMfneFloat::~CLmkMfneFloat()
+ {
+ delete iText;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::NewL
+// ---------------------------------------------------------
+//
+CLmkMfneFloat* CLmkMfneFloat::NewL(
+ TInt aMaxDigits,
+ TInt aMaxDecimalDigits)
+ {
+ CLmkMfneFloat* number = new(ELeave)
+ CLmkMfneFloat(aMaxDigits, aMaxDecimalDigits);
+
+ CleanupStack::PushL(number);
+ number->ConstructL();
+ CleanupStack::Pop();
+
+ return number;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::ConstructL
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::ConstructL()
+ {
+ iText = HBufC::NewL(MaxNumOfChars());
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::SetLimits
+// ---------------------------------------------------------
+//
+TBool CLmkMfneFloat::SetLimits(
+ TReal aMinimumValue,
+ TReal aMaximumValue)
+ {
+ __ASSERT_DEBUG(
+ Math::IsNaN(aMinimumValue) ||
+ Math::IsNaN(aMaximumValue) ||
+ (aMinimumValue < aMaximumValue), Panic(KErrArgument));
+
+ iMinimumValue = aMinimumValue;
+ iMaximumValue = aMaximumValue;
+
+ return EnsureValueInLimits(ValueFromText(*iText));
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::GetLimits
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::GetLimits(
+ TReal& aMinimumValue,
+ TReal& aMaximumValue) const
+ {
+ aMinimumValue = iMinimumValue;
+ aMaximumValue = iMaximumValue;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::SetValue
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::SetValue(TReal aValue)
+ {
+ TPtr ptr(iText->Des());
+ TextFromValue(aValue, ptr);
+ AknTextUtils::DisplayTextLanguageSpecificNumberConversion( ptr );
+ EnsureValueInLimits(aValue);
+ iIsBeingEditedWithCursor = EFalse;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::Value
+// ---------------------------------------------------------
+//
+TReal CLmkMfneFloat::Value() const
+ {
+ return ValueFromText(*iText);
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::MaximumWidthInPixels
+// ---------------------------------------------------------
+//
+TInt CLmkMfneFloat::MaximumWidthInPixels(
+ const CFont& aFont,
+ TBool /*aShrinkToMinimumSize*/)
+ {
+ TLocale locale;
+ TInt digitWidth =
+ TFindWidthOfWidestDigitType(locale.DigitType()).MaximumWidthInPixels(aFont);
+
+ return MaxNumOfChars() * digitWidth;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::InputCapabilities
+// ---------------------------------------------------------
+//
+TCoeInputCapabilities CLmkMfneFloat::InputCapabilities() const
+ {
+ return TCoeInputCapabilities(TCoeInputCapabilities::EWesternNumericReal);
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::IsEditable
+// ---------------------------------------------------------
+//
+TBool CLmkMfneFloat::IsEditable() const
+ {
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::HandleHighlight
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::HandleHighlight()
+ {
+ iFocus = ETrue;
+ if ((iText->Length() == 0))
+ {
+ iIsBeingEditedWithCursor = ETrue;
+ }
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::HighlightType
+// ---------------------------------------------------------
+//
+CEikMfneField::THighlightType CLmkMfneFloat::HighlightType() const
+ {
+ if (iFocus)
+ {
+ return iIsBeingEditedWithCursor ? ECursor : EInverseVideo;
+ }
+ else
+ {
+ return EInverseVideo;
+ }
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::HandleDeHighlight
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::HandleDeHighlight(
+ const CFont& /*aFont*/,
+ CEikonEnv& /*aEikonEnv*/,
+ TBool& aDataAltered,
+ TBool& /*aError*/)
+ {
+ iIsBeingEditedWithCursor = EFalse;
+ iFocus = EFalse;
+
+ TPtr text(iText->Des());
+ if (Math::IsNaN(ValueFromText(text)))
+ {
+ text.Zero();
+ aDataAltered = ETrue;
+ }
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::HandleKey
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::HandleKey(
+ const CFont& /*aFont*/,
+ const TKeyEvent& aKeyEvent,
+ TBool /*aInterpretLeftAndRightAsEarEvents*/,
+ TBool& aDataAltered,
+ TInt& aHighlightIncrement)
+ {
+ TChar ch = aKeyEvent.iCode;
+ TPtr text = iText->Des();
+
+ switch (ch)
+ {
+ case EKeyLeftArrow:
+ case EKeyRightArrow:
+ HandleLeftOrRightArrow(ch, aDataAltered, aHighlightIncrement);
+ break;
+
+ case EKeyBackspace:
+ if (text.Length())
+ {
+ iIsBeingEditedWithCursor = ETrue;
+ TrimRightmostChar(text);
+ if (text == KMinus)
+ {
+ text.Zero();
+ }
+ aDataAltered=ETrue;
+ }
+ break;
+
+ case KEventCodeStarSign:
+ case KEventCodeMinusSign:
+ // if negative values allowed
+ if (Math::IsNaN(iMinimumValue) || iMinimumValue < 0)
+ {
+ if (!iIsBeingEditedWithCursor)
+ {
+ iIsBeingEditedWithCursor = ETrue;
+ text.Zero();
+ }
+
+ if (text.Length() == 0)
+ {
+ text.Append(KMinus);
+ aDataAltered=ETrue;
+ }
+ }
+ break;
+
+ default:
+ TLocale locale;
+ TChar point = locale.DecimalSeparator();
+
+ if ((ch == KKeyToMatchPoint || ch == KPointKeyFromQwerty ) && (iIsBeingEditedWithCursor))
+ {
+ if (IsDecimalSeparatorAllowed(text))
+ {
+ text.Append(point);
+ aDataAltered = ETrue;
+ }
+ }
+
+ if (IsAnyDigit(ch))
+ {
+ if (!iIsBeingEditedWithCursor)
+ {
+ iIsBeingEditedWithCursor = ETrue;
+ text.Zero();
+ aDataAltered=ETrue;
+ }
+
+ if (IsMoreDigitsAllowed(text))
+ {
+ text.Append(ch);
+ aDataAltered = ETrue;
+
+ // check that value is within limits
+ if (EnsureValueInLimits(ValueFromText(text)))
+ {
+ // value is changed, make whole field selected
+ iIsBeingEditedWithCursor = EFalse;
+ }
+ }
+ else
+ {
+ aHighlightIncrement = 1;
+ }
+ }
+ break;
+ }
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::EnsureValueInLimits
+// ---------------------------------------------------------
+//
+TBool CLmkMfneFloat::EnsureValueInLimits(TReal aValue)
+ {
+ if ( !Math::IsNaN(aValue))
+ {
+ TPtr ptr(iText->Des());
+ if (aValue < iMinimumValue)
+ {
+ TextFromValue(iMinimumValue, ptr);
+ return ETrue;
+ }
+
+ if (aValue > iMaximumValue)
+ {
+ TextFromValue(iMaximumValue, ptr);
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::Text
+// ---------------------------------------------------------
+//
+const TDesC& CLmkMfneFloat::Text() const
+ {
+ TPtr ptr = (iText->Des());
+ AknTextUtils::DisplayTextLanguageSpecificNumberConversion( ptr );
+ return *iText;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::MaxNumOfChars
+// ---------------------------------------------------------
+//
+TInt CLmkMfneFloat::MaxNumOfChars() const
+ {
+ return iMaxDigits + KNumOtherSymbols;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::TextHasDecimalSeparator
+// ---------------------------------------------------------
+//
+TBool CLmkMfneFloat::IsDecimalSeparatorAllowed(const TDesC& aText) const
+ {
+ if (Math::IsNaN(ValueFromText(aText)))
+ {
+ return EFalse;
+ }
+
+ TLocale locale;
+ TChar point = locale.DecimalSeparator();
+ TInt i = 0;
+ while (i < aText.Length())
+ {
+ if (TChar(aText[i++]) == point)
+ {
+ return EFalse;
+ }
+ }
+
+ return (aText.Length() < MaxNumOfChars());
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::ValueFromText
+// ---------------------------------------------------------
+//
+TBool CLmkMfneFloat::IsMoreDigitsAllowed(const TDesC& aText) const
+ {
+ // check that number of allowed digits is less then iMaxDigits
+ TInt digits = 0, decimalDigits = 0;
+ TInt isDecimalPart = EFalse;
+ TLocale locale;
+ TChar point = locale.DecimalSeparator();
+
+ // if string starts with 0, then only decimal point is allowed
+ _LIT(KSingleZero, "0");
+ _LIT(KMinusZero, "-0");
+
+ if (aText == KSingleZero || aText == KMinusZero)
+ {
+ return EFalse;
+ }
+
+ // other cases - check total amount of digits
+ // and amount of decimal digits
+ for (TInt i = 0; i < aText.Length(); i++)
+ {
+ if (IsAnyDigit(aText[i]))
+ {
+ digits++;
+ }
+ if (isDecimalPart)
+ {
+ decimalDigits++;
+ }
+ if (aText[i] == point)
+ {
+ isDecimalPart = ETrue;
+ }
+ }
+ return ((digits < iMaxDigits) && (decimalDigits < iMaxDecimalDigits));
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::ValueFromText
+// ---------------------------------------------------------
+//
+TReal CLmkMfneFloat::ValueFromText(const TDesC& aText) const
+ {
+ if (aText.Length() == 0)
+ {
+ return Nan();
+ }
+
+ TBool isNegative(EFalse);
+ TInt integer(0);
+ TInt integerDigits(0);
+ TBool fractionPart(EFalse);
+ TInt fraction(0);
+ TInt fractionDigits(0);
+ TLocale locale;
+
+ for (TInt i = 0; i < aText.Length(); i++)
+ {
+ TChar ch(aText[i]);
+ if (ch == '-')
+ {
+ __ASSERT_DEBUG(i == 0, Panic(KErrGeneral));
+ isNegative = ETrue;
+ continue;
+ }
+
+ if (ch == locale.DecimalSeparator())
+ {
+ __ASSERT_DEBUG(fractionPart == EFalse, Panic(KErrGeneral));
+ fractionPart = ETrue;
+ continue;
+ }
+
+ TInt val = ch.GetNumericValue();
+ if (val >= 0)
+ {
+ if (!fractionPart)
+ {
+ integer = integer * 10 + val;
+ integerDigits++;
+ }
+ else
+ {
+ fraction = fraction * 10 + val;
+ fractionDigits++;
+ }
+ }
+ }
+
+ // integer part must contain at least "0".
+ if (integerDigits < 1)
+ {
+ return Nan();
+ }
+
+ TReal value(fraction);
+ for (TInt i = 0; i < fractionDigits; i++)
+ {
+ value /= 10;
+ }
+
+ value += TReal(integer);
+ return (isNegative) ? -value : value;
+ }
+
+// ---------------------------------------------------------
+// CLmkMfneFloat::TextFromValue
+// ---------------------------------------------------------
+//
+void CLmkMfneFloat::TextFromValue(TReal aValue, TDes& aText) const
+ {
+ aText.SetLength(0);
+
+ if (Math::IsNaN(aValue))
+ {
+ return;
+ }
+
+ TRealFormat format;
+ format.iType = KRealFormatFixed;
+ format.iTriLen = 0; // no triad separations
+ format.iWidth = MaxNumOfChars();
+ format.iPlaces = (aValue == 0) ? 0 : iMaxDecimalDigits;
+
+ // convert real value to a string
+ aText.Num(aValue, format);
+
+ // cut trailing zeroes from decimal part
+ TLocale locale;
+ TInt pointIndex = aText.Locate(locale.DecimalSeparator());
+ if (pointIndex != KErrNotFound)
+ {
+ TInt newLength = aText.Length();
+ for (TInt i = aText.Length() - 1; i > pointIndex; i--)
+ {
+ if (aText[i] == '0')
+ {
+ newLength--;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // if only decimal point left, cut it also
+ if (aText[newLength-1] == locale.DecimalSeparator())
+ {
+ newLength--;
+ }
+
+ aText.SetLength(newLength);
+ }
+ }