--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtconstrainedtext.cpp Wed Sep 01 12:33:18 2010 +0100
@@ -0,0 +1,1064 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Nokia Corporation - S60 implementation
+ *******************************************************************************/
+
+
+#include <eikedwin.h>
+#include <AknNumEdwin.h>
+#include <eikfpne.h>
+#include <eswtcore.rsg>
+#include <avkon.hrh>
+#include "swtcontrolhelper.h"
+#include "swtconstrainedtext.h"
+#include "swtedwin.h"
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::CSwtConstrainedText
+// --------------------------------------------------------------------------------
+//
+inline CSwtConstrainedText::CSwtConstrainedText(MSwtDisplay& aDisplay,
+ TSwtPeer aPeer,
+ MSwtComposite& aParent,
+ TInt aStyle)
+ : CSwtTextBase(aDisplay, aPeer, aParent, aStyle)
+ , iTextLimit(MSwtText::ETextLimit)
+{
+ // Set decimal separator according to the current locale.
+ // Note: decimal separators other than ',' and '.' are currently not supported
+ TLocale loc;
+ iDecimalSeparator = loc.DecimalSeparator();
+ if (iDecimalSeparator != ',')
+ {
+ iDecimalSeparator = '.';
+ }
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::~CSwtConstrainedText
+// --------------------------------------------------------------------------------
+//
+CSwtConstrainedText::~CSwtConstrainedText()
+{
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::NewL
+// --------------------------------------------------------------------------------
+//
+CSwtConstrainedText* CSwtConstrainedText::NewL(MSwtDisplay& aDisplay,
+ TSwtPeer aPeer,
+ MSwtComposite& aParent,
+ TInt aStyle)
+{
+ CSwtConstrainedText* self = new(ELeave) CSwtConstrainedText(aDisplay,
+ aPeer, aParent, aStyle);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtConstrainedText::Draw
+// ---------------------------------------------------------------------------
+//
+void CSwtConstrainedText::Draw(const TRect& /*aRect*/) const
+{
+ if (GetShell().UrgentPaintControl() == this)
+ return;
+
+ CEikEdwin& editor(Editor());
+ if (editor.TextView() == NULL)
+ {
+ return;
+ }
+
+ // Update editor's visibility, otherwise text will be drawn
+ // when performing clipboard operations on invisible control.
+ const TBool visible = GetVisibleRecursively();
+ if (visible != editor.IsVisible())
+ {
+ editor.MakeVisible(visible);
+ }
+
+ // Update custom clipping, otherwise edwin will draw outside of
+ // its parent control.
+ TRect clipRect(ClipToVisibleRect(editor.TextView()->ViewRect()));
+ if (clipRect != iLastViewVisibleRect)
+ {
+ switch (iConstraint)
+ {
+ case ENumeric:
+ ((CSwtIntegerEdwin*)&editor)->SetClippingRect(clipRect);
+ break;
+ case EDecimal:
+ ((CSwtFloatingPointEdwin*)&editor)->SetClippingRect(clipRect);
+ break;
+ case EPhoneNumber:
+ ((CSwtEdwin*)&editor)->SetClippingRect(clipRect);
+ break;
+ default:
+ ASSERT(EFalse);
+ break;
+ }
+ iLastViewVisibleRect = clipRect;
+ }
+}
+
+// --------------------------------------------------------------------------------
+// Checks the content will remain valid if the specified text replaces
+// the given range.
+// --------------------------------------------------------------------------------
+//
+inline TInt CSwtConstrainedText::LooseCheckReplacementL(TInt aStart,
+ TInt aEnd,
+ const TDesC& aText) const
+{
+ return CheckReplacementL(aStart, aEnd, aText, EFalse);
+}
+
+
+// --------------------------------------------------------------------------------
+// Checks the content will remain valid if the specified character replaces
+// the given range.
+// --------------------------------------------------------------------------------
+TInt CSwtConstrainedText::LooseCheckReplacementL(TInt aStart,
+ TInt aEnd,
+ TInt aChar) const
+{
+ TBuf<1> buf;
+ buf.Append(aChar);
+ return LooseCheckReplacementL(aStart, aEnd, buf);
+}
+
+
+// --------------------------------------------------------------------------------
+// Checks the content will remain valid if the specified text replaces
+// the current selection.
+// --------------------------------------------------------------------------------
+inline TInt CSwtConstrainedText::StrictCheckReplacementL(const TDesC& aText) const
+{
+ const TCursorSelection sel(Editor().Selection());
+ return CheckReplacementL(sel.LowerPos(), sel.HigherPos(), aText, ETrue);
+}
+
+
+// --------------------------------------------------------------------------------
+// Checks the content will remain valid if the specified text replaces
+// the given range.
+// --------------------------------------------------------------------------------
+TInt CSwtConstrainedText::CheckReplacementL(TInt aStart,
+ TInt aEnd,
+ const TDesC& aText,
+ TBool aStrict) const
+{
+
+ ASSERT(aStart <= aEnd);
+
+ const TInt selLength = aEnd - aStart;
+
+ const TInt bufLength = Editor().TextLength() + Max(0, aText.Length() - selLength);
+ HBufC* buf = HBufC::NewLC(bufLength);
+ TPtr ptr(buf->Des());
+ Editor().GetText(ptr);
+ ptr.Delete(aStart, selLength);
+ ptr.Insert(aStart, aText);
+ TInt result = (aStrict) ? StrictValidateText(*buf) : LooseValidateText(*buf);
+ CleanupStack::PopAndDestroy(buf);
+ return result;
+}
+
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::LooseValidateText
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::LooseValidateText(const TDesC& aText) const
+{
+ switch (iConstraint)
+ {
+ case ENumeric:
+ return LooseValidateNumeric(aText);
+ case EDecimal:
+ return LooseValidateDecimal(aText);
+ case EPhoneNumber:
+ return ValidatePhoneNumber(aText);
+ default:
+ ASSERT(EFalse);
+ return KErrNone;
+ }
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::StrictValidateText
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::StrictValidateText(const TDesC& aText) const
+{
+ switch (iConstraint)
+ {
+ case ENumeric:
+ return StrictValidateNumeric(aText);
+ case EDecimal:
+ return StrictValidateDecimal(aText);
+ case EPhoneNumber:
+ return ValidatePhoneNumber(aText);
+ default:
+ ASSERT(EFalse);
+ return KErrNone;
+ }
+}
+
+// --------------------------------------------------------------------------------
+// Checks whether a given text is an acceptable NUMERIC. It must be
+// made of digits only and an optional leading minus sign. If the
+// maximum text size is 1, then no minus sign is allowed.
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::LooseValidateNumeric(const TDesC& aText) const
+{
+ const TText* ptr = aText.Ptr();
+
+ // Likely text will be appended, so we perform checking backwards for faster execution
+ for (TInt pos=aText.Length(); pos>0;)
+ {
+ TChar ch(ptr[--pos]);
+ if (!ch.IsDigit() && !(ch == '-' && (pos == 0 && iTextLimit != 1)))
+ {
+ return KErrArgument;
+ }
+ }
+
+ return KErrNone;
+}
+
+// --------------------------------------------------------------------------------
+// Strict version of the NUMERIC check. Same as the loose one except a "-" is
+// no longer accepted.
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::StrictValidateNumeric(const TDesC& aText) const
+{
+ _LIT(KMinus, "-");
+ if (aText.Compare(KMinus) == 0)
+ {
+ return KErrArgument;
+ }
+ return LooseValidateNumeric(aText);
+}
+
+// --------------------------------------------------------------------------------
+// Checks whether a text is an acceptable DECIMAL. It consists of an
+// optional minus sign '-', followed by one or more whole-number
+// decimal digits, followed by an optional fraction separator,
+// followed by zero or more decimal fraction digits. The whole-number
+// decimal digits may be omitted if the fraction separator and one or
+// more decimal fraction digits are present.
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::LooseValidateDecimal(const TDesC& aText) const
+{
+ TInt len = aText.Length();
+ TInt pos = 0;
+ const TText* ptr = aText.Ptr();
+
+ if (len == 0)
+ {
+ return KErrNone;
+ }
+
+ // '-' is allowed only in the begining of the text and limit>1
+ if (ptr[0] == '-')
+ {
+ pos = 1;
+ //'.' is not allowed when first character is '-' and limit is 2
+ if ((pos<len && (TChar(ptr[pos]) == iDecimalSeparator) && iTextLimit == 2))
+ {
+ return KErrArgument;
+ }
+ }
+
+ for (TInt pos1=aText.Length(); pos1>0;)
+ {
+ TChar ch(ptr[--pos1]);
+ //'-', '.' is not allowed when limit is 1
+ if (((ch == '-' || ch == iDecimalSeparator) && (pos1 == 0 && iTextLimit == 1)))
+ {
+ return KErrArgument;
+ }
+ }
+
+ // allows all digits, and allow only one '.'
+ TBool valid = ETrue;
+ while (pos<len && (TChar(ptr[pos]).IsDigit() ||
+ (TChar(ptr[pos]) == iDecimalSeparator && valid)))
+ {
+ if (TChar(ptr[pos]) == iDecimalSeparator)
+ {
+ valid = EFalse;
+ }
+ ++pos;
+ }
+ return (pos == len) ? KErrNone : KErrArgument;
+}
+
+
+// --------------------------------------------------------------------------------
+// Strict version of the DECIMAL check. Same as the loose one except "-", "."
+// and "-." are no longer accepted.
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::StrictValidateDecimal(const TDesC& aText) const
+{
+ _LIT(KMinus, "-");
+
+ TBuf<1> point;
+ point.Append(iDecimalSeparator);
+
+ TBuf<2> minusPoint;
+ minusPoint.Append(KMinus);
+ minusPoint.Append(iDecimalSeparator);
+
+ if (aText.Compare(KMinus) == 0 || aText.Compare(point) == 0 ||
+ aText.Compare(minusPoint) == 0)
+ {
+ return KErrArgument;
+ }
+ return LooseValidateDecimal(aText);
+}
+
+
+// --------------------------------------------------------------------------------
+// Checks if a character is acceptable in a phone number
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::IsPhoneNumberChar(const TChar &aChar,
+ const TDesC& aAllowedChars)
+{
+ // Well, digits and space: of course
+ if (aChar.IsDigit() || aChar==' ')
+ {
+ return ETrue;
+ }
+
+
+ // Is it one of the other allowed chars
+ TInt len = aAllowedChars.Length();
+ for (TInt i = 0; i<len; ++i)
+ {
+ if (aChar == TChar(aAllowedChars[i]))
+ {
+ return ETrue;
+ }
+ }
+
+ // Not a phone number character
+ return EFalse;
+}
+
+
+// --------------------------------------------------------------------------------
+// Checks if a text is a correct PHONENUMBER. Checks it contains only
+// allowed characters, no syntax checking.
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::ValidatePhoneNumber(const TDesC& aText)
+{
+
+ _LIT(KDefaultSpecialChars, "*#+ABCD,T!@;IiGg>()wpWP");
+
+ // Load the list of allowed chars from resource
+ const TDesC* allowed = &KDefaultSpecialChars;
+
+ // Likely text will be appended, so we perform checking backwards for faster execution
+ const TText* ptr = aText.Ptr();
+ for (TInt i=aText.Length(); i>0;)
+ {
+ if (!IsPhoneNumberChar(ptr[--i], *allowed))
+ {
+ return KErrArgument;
+ }
+ }
+
+ return KErrNone;
+}
+
+// --------------------------------------------------------------------------------
+// Converts decimal point, if any, to a localized decimal separator.
+// --------------------------------------------------------------------------------
+//
+HBufC* CSwtConstrainedText::ConvertToLocalizedDecimalLC(const TDesC& aText)
+{
+ HBufC* buf = aText.AllocLC();
+ TPtr text = buf->Des();
+ TInt pos = buf->Length();
+ for (; pos>0;)
+ {
+ TText& ch = text[--pos];
+ if (ch == '.')
+ ch = (TText)iDecimalSeparator;
+ }
+ return buf;
+}
+
+// --------------------------------------------------------------------------------
+// Converts localized decimal separator, if any, to a decimal point.
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::ConvertFromLocalizedDecimal(HBufC* buf) const
+{
+ TPtr text = buf->Des();
+ TInt pos = buf->Length();
+ for (; pos>0;)
+ {
+ TText& ch = text[--pos];
+ if (ch == (TText)iDecimalSeparator)
+ ch = '.';
+ }
+}
+
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::IsNavigationKey
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::IsNavigationKey(const TKeyEvent& aKeyEvent) const
+{
+ switch (aKeyEvent.iScanCode)
+ {
+ case EStdKeyDownArrow:
+ case EStdKeyUpArrow:
+ case EStdKeyLeftArrow:
+ case EStdKeyRightArrow:
+ case EStdKeyEscape:
+ case EStdKeyPageUp:
+ case EStdKeyPageDown:
+ case EStdKeyHome:
+ case EStdKeyEnd:
+ return ETrue;
+ default:
+ return EFalse;
+ }
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::IsHotKeyL
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::IsHotKeyL(const TKeyEvent& aKeyEvent) const
+{
+
+ switch (HotKeyL(aKeyEvent))
+ {
+ case CEikEdwin::EHotKeyCut:
+ case CEikEdwin::EHotKeyCopy:
+ case CEikEdwin::EHotKeyPaste:
+ case CEikEdwin::EHotKeyUndo:
+ case CEikEdwin::EHotKeyFind:
+ case CEikEdwin::EHotKeyInsertChar:
+ return ETrue;
+ default:
+ return EFalse;
+ }
+}
+
+// --------------------------------------------------------------------------------
+// Virtual methods from CCoeControl
+// --------------------------------------------------------------------------------
+//
+TKeyResponse CSwtConstrainedText::OfferKeyEventL(const TKeyEvent& aKeyEvent,
+ TEventCode aType)
+{
+ TBool traversalDoIt = ETrue;
+
+ // Set the traversal do-it default to false for the following cases:
+
+ // Escape
+ if (aKeyEvent.iCode == EKeyEscape)
+ {
+ traversalDoIt = EFalse;
+ }
+ // Left and Right arrows : do not allow traversal
+ else if (aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyRightArrow)
+ {
+ traversalDoIt = EFalse;
+ }
+ return CSwtTextBase::HandleKeyL(aKeyEvent, aType, traversalDoIt);
+}
+
+// --------------------------------------------------------------------------------
+// Virtual methods from MSwtControl
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::ProcessKeyEventL(const TKeyEvent& aKeyEvent,
+ TEventCode aType)
+{
+ if (aType != EEventKey)
+ {
+ return;
+ }
+
+
+ // Read-only: CEikEdwin displays a message and leaves. We want the message
+ // but not the leaving, hence the trap.
+ if (iStyle & KSwtStyleReadOnly)
+ {
+ TRAP_IGNORE(ForwardKeyEventL(aKeyEvent, aType));
+ return;
+ }
+
+ // We're single-line: enter not consumed, translated to default selection event
+ if (aKeyEvent.iCode == EKeyEnter)
+ {
+ iDisplay.PostDefaultSelectionEventL(iPeer);
+ return;
+ }
+
+
+ const TInt modifiers = aKeyEvent.iModifiers & ECtrlFuncShiftMask;
+ const TCursorSelection selection(Editor().Selection());
+ const TInt selStart = selection.LowerPos();
+ const TInt selEnd = selection.HigherPos();
+ const TInt selLength = selEnd - selStart;
+ const TInt length = Editor().TextLength();
+ const TInt hotkey = HotKeyL(aKeyEvent);
+
+ TBool notify = ETrue;
+ TInt validity;
+
+ // Cut
+ if (hotkey == CEikEdwin::EHotKeyCut)
+ {
+ validity = LooseCheckReplacementL(selStart, selEnd, KNullDesC);
+ }
+ // Paste
+ else if (hotkey == CEikEdwin::EHotKeyPaste)
+ {
+ TPtrC content(SwtControlHelper::GetClipboardTextContentLC());
+ if (content.Length() == 0)
+ {
+ // Nothing to paste: CEikEdwin displays a message and leaves. We want
+ // the message but not the leaving, hence the trap.
+ TRAP_IGNORE(ForwardKeyEventL(aKeyEvent, aType));
+ return;
+ }
+
+ validity = LooseCheckReplacementL(selStart, selEnd, content);
+ if (content.Ptr())
+ {
+ CleanupStack::PopAndDestroy(&content);
+ }
+ }
+ // Undo
+ else if (hotkey == CEikEdwin::EHotKeyUndo)
+ {
+ validity = KErrNone;
+ }
+ // Delete
+ else if (aKeyEvent.iCode == EKeyDelete && modifiers == 0)
+ {
+ if (selLength != 0)
+ {
+ validity = LooseCheckReplacementL(selStart, selEnd, KNullDesC);
+ }
+ else if (selection.iCursorPos < length)
+ {
+ validity = LooseCheckReplacementL(selection.iCursorPos,
+ selection.iCursorPos+1, KNullDesC);
+ }
+
+ else
+ {
+ validity = KErrArgument;
+ }
+ }
+ // Backspace
+ else if (aKeyEvent.iCode == EKeyBackspace && modifiers == 0)
+ {
+ if (selLength != 0)
+ {
+ validity = LooseCheckReplacementL(selStart, selEnd, KNullDesC);
+ }
+ else if (selection.iCursorPos > 0)
+ {
+ validity = LooseCheckReplacementL(selection.iCursorPos-1, selection.iCursorPos, KNullDesC);
+ }
+ else
+ {
+ validity = KErrArgument;
+ }
+ }
+ // Ctrl+Minus: non-breaking hyphen
+ else if (aKeyEvent.iCode=='-' && (modifiers & EModifierCtrl))
+ {
+ validity = LooseCheckReplacementL(selStart, selEnd, CEditableText::ENonBreakingHyphen);
+ }
+ // Shift+Space: non-breaking space
+ else if (aKeyEvent.iCode == ' ' && (modifiers & EModifierShift))
+ {
+ validity = LooseCheckReplacementL(selStart, selEnd, CEditableText::ENonBreakingSpace);
+ }
+ // Regular character
+ else if (aKeyEvent.iCode == EKeyTab || TChar(aKeyEvent.iCode).IsPrint())
+ {
+ validity = LooseCheckReplacementL(selStart, selEnd, aKeyEvent.iCode);
+ }
+ // Other (navigation mostly)
+ else
+ {
+ validity = KErrNone;
+ notify = EFalse;
+ }
+
+ if (validity == KErrNone)
+ {
+ ForwardKeyEventL(aKeyEvent, aType);
+ if (notify)
+ {
+ iDisplay.PostModifyEventL(iPeer);
+ }
+
+ }
+}
+
+// --------------------------------------------------------------------------------
+// Virtual methods from MSwtConstrainedText
+// --------------------------------------------------------------------------------
+//
+MSwtControl* CSwtConstrainedText::Control()
+{
+ return this;
+}
+
+// --------------------------------------------------------------------------------
+// This is actually the 3rd-time constructor. This is where the actual editor
+// is constructed (couldn't be before we set the constraint).
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::SetConstraintL(TConstraint aConstraint)
+{
+ ASSERT(iConstraint == 0);
+ ASSERT(aConstraint != 0);
+
+
+ // Construct the control
+ CEikEdwin* editor = NULL;
+
+ switch (aConstraint)
+ {
+ case ENumeric:
+ {
+ editor = new(ELeave)CSwtIntegerEdwin;
+ SetEditor(editor);
+ editor->ConstructL(-KMaxTInt, KMaxTInt, iTextLimit);
+ editor->SetTextLimit(iTextLimit);
+ editor->SetAknEditorCase(EAknSCTNumeric);
+ editor->SetAknEditorAllowedInputModes(EAknEditorNumericInputMode);
+ editor->SetAknEditorInputMode(EAknEditorNumericInputMode);
+ editor->SetAknEditorCurrentInputMode(EAknEditorNumericInputMode);
+ editor->SetAknEditorNumericKeymap(EAknEditorPlainNumberModeKeymap);
+ editor->SetAknEditorFlags(EAknEditorFlagFixedCase
+ | EAknEditorFlagNoT9
+ | EAknEditorFlagUseSCTNumericCharmap
+ | EAknEditorFlagDeliverVirtualKeyEventsToApplication
+#ifdef RD_JAVA_S60_RELEASE_9_2
+ | EAknEditorFlagEnablePartialScreen
+#endif // RD_JAVA_S60_RELEASE_9_2
+ );
+ editor->SetAknEditorSpecialCharacterTable(R_ESWT_CONSTRAINEDTEXT_NUMERIC_MODE_DIALOG);
+ }
+ break;
+ case EDecimal:
+ {
+ editor = new(ELeave) CSwtFloatingPointEdwin;
+ SetEditor(editor);
+ editor->ConstructL(-KMaxTInt, KMaxTInt, iTextLimit);
+ editor->SetAknEditorCase(EAknSCTNumeric);
+ editor->SetAknEditorAllowedInputModes(EAknEditorNumericInputMode);
+ editor->SetAknEditorInputMode(EAknEditorNumericInputMode);
+ editor->SetAknEditorCurrentInputMode(EAknEditorNumericInputMode);
+ editor->SetAknEditorNumericKeymap(EAknEditorPlainNumberModeKeymap);
+
+ editor->SetAknEditorFlags(EAknEditorFlagFixedCase
+ | EAknEditorFlagNoT9
+ | EAknEditorFlagUseSCTNumericCharmap
+ | EAknEditorFlagDeliverVirtualKeyEventsToApplication
+#ifdef RD_JAVA_S60_RELEASE_9_2
+ | EAknEditorFlagEnablePartialScreen
+#endif // RD_JAVA_S60_RELEASE_9_2
+ );
+
+ if (iDecimalSeparator == ',')
+ {
+ editor->SetAknEditorSpecialCharacterTable(R_ESWT_CONSTRAINEDTEXT_DECIMAL_MODE_WITH_COMMA_DIALOG);
+ }
+ else
+ {
+ editor->SetAknEditorSpecialCharacterTable(R_ESWT_CONSTRAINEDTEXT_DECIMAL_MODE_DIALOG);
+ }
+ }
+ break;
+ case EPhoneNumber:
+ {
+ const TUint flags = CEikEdwin::ESegmentedStorage | CEikEdwin::ELineCursor
+ | CEikEdwin::EInclusiveSizeFixed | CEikEdwin::ENoAutoSelection
+ | CEikEdwin::EResizable | CEikEdwin::EWidthInPixels
+ | CEikEdwin::ENoWrap;
+ editor = new(ELeave) CSwtEdwin;
+ SetEditor(editor);
+ editor->ConstructL(flags, 0, iTextLimit, 1);
+ editor->SetAknEditorCase(EAknSCTNumeric);
+ editor->SetAknEditorAllowedInputModes(EAknEditorNumericInputMode);
+ editor->SetAknEditorInputMode(EAknEditorNumericInputMode);
+ editor->SetAknEditorNumericKeymap(EAknEditorAlphanumericNumberModeKeymap);
+ editor->SetAknEditorFlags(EAknEditorFlagUseSCTNumericCharmap
+ | EAknEditorFlagDeliverVirtualKeyEventsToApplication
+#ifdef RD_JAVA_S60_RELEASE_9_2
+ | EAknEditorFlagEnablePartialScreen
+#endif // RD_JAVA_S60_RELEASE_9_2
+ );
+ editor->SetAknEditorSpecialCharacterTable(R_ESWT_CONSTRAINEDTEXT_PHONENUMBER_MODE_DIALOG);
+ }
+ break;
+ default:
+ ASSERT(EFalse);
+ break;
+ }
+
+ editor->SetContainerWindowL(*this);
+
+ editor->CreateTextViewL();
+ editor->MakeVisible(IsVisible());
+ editor->SetDimmed(IsDimmed());
+ editor->SetPosition(iPosition);
+ editor->AddEdwinObserverL(this);
+ ActivateL();
+
+ RetrieveDefaultFontL();
+ FixPadding();
+
+ iConstraint = aConstraint;
+
+ // Needs to be done after the ActivateL method.
+ InitControlBaseL();
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::GetTextL
+// --------------------------------------------------------------------------------
+//
+HBufC* CSwtConstrainedText::GetTextL() const
+{
+ HBufC* buf = Editor().GetTextInHBufL();
+ if (!buf)
+ {
+ buf = HBufC::NewL(0);
+ }
+ // convert decimal from localized to MIDlet-visible representation
+ if (iConstraint & EDecimal)
+ {
+ ConvertFromLocalizedDecimal(buf);
+ }
+ return buf;
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::SetTextL
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::SetTextL(const TDesC& aText)
+{
+ TBool val;
+ if (iConstraint & EDecimal)
+ {
+ HBufC* buf = ConvertToLocalizedDecimalLC(aText);
+ TPtr ptr = buf->Des();
+ User::LeaveIfError(StrictValidateText(ptr));
+ val = CSwtTextBase::SetTextL(ptr);
+ CleanupStack::PopAndDestroy(buf);
+ }
+ else
+ {
+ User::LeaveIfError(StrictValidateText(aText));
+ val = CSwtTextBase::SetTextL(aText);
+ }
+ return val;
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::AppendL
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::AppendL(const TDesC& aText)
+{
+ const TInt len = Editor().TextLength();
+
+ // Ensure content will be valid
+ HBufC* buf = HBufC::NewLC(len + aText.Length());
+ TPtr ptr(buf->Des());
+ Editor().GetText(ptr);
+
+ TBool val;
+ if (iConstraint & EDecimal)
+ {
+ HBufC* afterLocDec = ConvertToLocalizedDecimalLC(aText);
+ TPtr locPtr = afterLocDec->Des();
+ ptr.Append(locPtr);
+
+ User::LeaveIfError(StrictValidateText(*buf));
+
+ val = CSwtTextBase::AppendL(locPtr);
+ CleanupStack::PopAndDestroy(afterLocDec);
+ }
+ else
+ {
+ ptr.Append(aText);
+ User::LeaveIfError(StrictValidateText(*buf));
+ val = CSwtTextBase::AppendL(aText);
+ }
+ CleanupStack::PopAndDestroy(buf);
+
+ return val;
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::InsertL
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::InsertL(const TDesC& aText)
+{
+ TBool val;
+ if (iConstraint & EDecimal)
+ {
+ HBufC* buf = ConvertToLocalizedDecimalLC(aText);
+ TPtr ptr = buf->Des();
+ User::LeaveIfError(StrictCheckReplacementL(ptr));
+ val = CSwtTextBase::InsertL(ptr);
+ CleanupStack::PopAndDestroy(buf);
+ }
+ else
+ {
+ User::LeaveIfError(StrictCheckReplacementL(aText));
+ val = CSwtTextBase::InsertL(aText);
+ }
+ return val;
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::GetCharCount
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::GetCharCount() const
+{
+ return Editor().TextLength();
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::SetTextLimit
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::SetTextLimitL(TInt aLimit)
+{
+ iTextLimit = aLimit;
+ return CSwtTextBase::SetLimitL(aLimit);
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::GetCaretPosition
+// --------------------------------------------------------------------------------
+//
+TInt CSwtConstrainedText::GetCaretPosition() const
+{
+ return Editor().CursorPos();
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::SetSelectionL
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::SetSelectionL(TInt aStart, TInt aEnd)
+{
+ const TInt len = Editor().TextLength();
+ if (aStart>len || aEnd>len)
+ {
+ User::Leave(ESwtErrorInvalidRange);
+ }
+
+ Editor().SetSelectionL(aEnd, aStart);
+ // This is neccessary, since CEikEdwin doesn't really set the selection
+ // until drawing occurs and clipboard operations can be
+ // broken in such a case
+ Editor().TextView()->SetSelectionL(TCursorSelection(aEnd, aStart));
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::ClearSelectionL
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::ClearSelectionL()
+{
+ TCursorSelection selection(Editor().Selection());
+ Editor().SetSelectionL(selection.iCursorPos, selection.iCursorPos);
+ Editor().TextView()->SetSelectionL(TCursorSelection(selection.iCursorPos,
+ selection.iCursorPos));
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::SelectAllL
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::SelectAllL()
+{
+ const TInt length = Editor().TextLength();
+ Editor().SetSelectionL(length, 0);
+ Editor().TextView()->SetSelectionL(TCursorSelection(length, 0));
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::ShowSelectionL
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::ShowSelectionL()
+{
+ TCursorSelection selection(Editor().Selection());
+ Editor().SetSelectionL(selection.iCursorPos, selection.iAnchorPos);
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::CutL
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::CutL()
+{
+ const TCursorSelection selection(Editor().Selection());
+ const TInt selLength = selection.Length();
+
+ // Ensure content will be valid
+ if (selLength != 0)
+ {
+ HBufC* text = Editor().GetTextInHBufL();
+ TPtr ptr(text->Des());
+ ptr.Delete(selection.LowerPos(), selLength);
+ TInt error = StrictValidateText(ptr);
+ delete text;
+ User::LeaveIfError(error);
+ }
+
+ return CSwtTextBase::CutL();
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::CopyL
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::CopyL()
+{
+ Editor().ClipboardL(CEikEdwin::ECopy);
+}
+
+// --------------------------------------------------------------------------------
+//CSwtConstrainedText::PasteL
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::PasteL()
+{
+ // Ensure content will be valid
+ TPtrC content(SwtControlHelper::GetClipboardTextContentLC());
+ TInt clipboardLength = content.Length();
+ User::LeaveIfError(StrictCheckReplacementL(content));
+ if (content.Ptr())
+ {
+ CleanupStack::PopAndDestroy();
+ }
+
+
+ if (clipboardLength == 0)
+ {
+ // Nothing to paste: CEikEdwin displays a message and leaves. We want
+ // the message but not the leaving, hence the trap.
+ TRAP_IGNORE(Editor().ClipboardL(CEikEdwin::EPaste));
+ return EFalse;
+ }
+
+ Editor().ClipboardL(CEikEdwin::EPaste);
+ return ETrue;
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::GetEditable
+// --------------------------------------------------------------------------------
+//
+TBool CSwtConstrainedText::GetEditable() const
+{
+ return CSwtTextBase::GetEditable();
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::SetEditable
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::SetEditable(TBool aEditable)
+{
+ CSwtTextBase::SetEditable(aEditable);
+}
+
+// --------------------------------------------------------------------------------
+// CSwtConstrainedText::HandleEdwinEventL
+// --------------------------------------------------------------------------------
+//
+void CSwtConstrainedText::HandleEdwinEventL(CEikEdwin */*aEdwin*/, TEdwinEvent aEventType)
+{
+ switch (aEventType)
+ {
+ case EEventTextUpdate:
+ {
+ TInt textLength = Editor().TextLength();
+ TInt caretPos = GetCaretPosition();
+ if ((iConstraint & ENumeric ||
+ iConstraint & EDecimal) && (textLength > 0 && caretPos > 0))
+ {
+
+ CPlainText* editorText = Editor().Text();
+ TPtrC ptr(editorText->Read(0));
+
+ TBool valid = ptr[caretPos - 1] == iDecimalSeparator;
+ //'-' is not allowed when limit is 1 or in the middle of the text in
+ // both Numeric and Decimal
+ if (ptr[caretPos - 1] == '-'
+ && (caretPos > 1 || iTextLimit == 1))
+ {
+ editorText->DeleteL(caretPos - 1, 1);
+ caretPos--;
+ }
+ //'.' is not allowed when more than one dot or limit is 1 or
+ // first character is '-' and limit is 2 in Decimal style
+ if (iConstraint & EDecimal)
+ {
+ if (valid)
+ {
+ if (iTextLimit == 1 || (ptr[0] == '-' && iTextLimit == 2) ||
+ caretPos-1 != ptr.LocateF(iDecimalSeparator) ||
+ caretPos-1 != ptr.LocateReverseF(iDecimalSeparator))
+ {
+ editorText->DeleteL(caretPos - 1, 1);
+ caretPos--;
+ }
+ }
+ }
+ Editor().HandleTextChangedL();
+ Editor().SetSelectionL(caretPos, caretPos);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}