diff -r f5050f1da672 -r 04becd199f91 javauis/lcdui_akn/lcdui/src/CMIDTextBoxQueryDialog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/lcdui/src/CMIDTextBoxQueryDialog.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,1454 @@ +/* +* Copyright (c) 2008 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: Popu-up TextBox dialog implementation for S60 +* +*/ + +#include +#include "CMIDTextBoxQueryDialog.h" + +#include "lcdui.hrh" +#include +#include + +#include "CMIDEdwinUtils.h" + +#include +#include +#include + +#include +#include + +// FEP CR +// constants for FEP +#include +#include + +// CAknExtendedInputCapabilities for extended input capabilities +#include + +// sound files +#include +#include + +// aiw used to invoke phonebook +#include +// phone client API classes for starting phone call +#include +#include +#include + + +#include + +CMIDTextBoxQueryDialog* CMIDTextBoxQueryDialog::NewLC(TInt aConstraints, + TDes& aResult, + TInt aMaxSize, + CMIDDisplayable* aDisplayable, + const TDesC& aText) +{ + CMIDTextBoxQueryDialog* self = new(ELeave) CMIDTextBoxQueryDialog(aResult); + CleanupStack::PushL(self); + self->ConstructL(aConstraints, aMaxSize, aDisplayable, aText); + return self; +} + +CMIDTextBoxQueryDialog::~CMIDTextBoxQueryDialog() +{ + delete iAiwPbkClient; + delete iEdwinUtils; + RemoveNonMidletCommands(); +} + +void CMIDTextBoxQueryDialog::ConstructL(TInt aConstraints, + TInt aMaxSize, + CMIDDisplayable* aDisplayable, + const TDesC& aText) +{ + TLocale loc; + iDecimalSeparator = loc.DecimalSeparator(); + if (iDecimalSeparator != ',') + { + iDecimalSeparator = '.'; + } + + iEdwinUtils = CMIDEdwinUtils::NewL(this, iDecimalSeparator); + + iConstraints = aConstraints; + + // if text is invalid according to constraints, throw IllegalArgumentException, + // except for a PHONENUMBER which only has the invalid characters removed + if ((iConstraints & MMIDTextField::EConstraintMask) != MMIDTextField::EPhoneNumber + && !iEdwinUtils->ConstraintsValidForText(aText,iConstraints,ETrue)) + { + User::Leave(KErrArgument); + } + + iMaxSize = aMaxSize; + iDisplayable = aDisplayable; + + // This is aprotected method call must be inside the class itself. + // ConstructSleepingDialogL is replacing the call of ReadResourceLC + // in CMIDTextBoxDialogControl::CreateTextBoxQueryDialogL + ConstructSleepingDialogL(R_MIDP_POPUP_TEXTBOX); +} + +CMIDTextBoxQueryDialog::CMIDTextBoxQueryDialog(TDes& aResult) + : CAknTextQueryDialog(aResult, CAknQueryDialog::ENoTone) +{ +} + +TInt CMIDTextBoxQueryDialog::RouseSleepingDialog() +{ + return CAknTextQueryDialog::RouseSleepingDialog(); +} + +void CMIDTextBoxQueryDialog::ExitSleepingDialog() +{ + CAknTextQueryDialog::ExitSleepingDialog(); +} + +void CMIDTextBoxQueryDialog::TryExitL(TInt aButtonId) +{ + iDisplayable->MenuHandler()->ProcessCommandL(aButtonId); +} + +TBool CMIDTextBoxQueryDialog::ProcessCommandL(CMIDCommand* aCommand) +{ + ASSERT(aCommand); + TBool ret = EFalse; + + switch (aCommand->Id()) + { + case CMIDEdwinUtils::EMenuCommandFetchPhoneNumber: + // for fetching data from phonebook + if (!iAiwPbkClient) + { + iAiwPbkClient = CMIDAiwPbk2Client::NewL(*this); + } + iAiwPbkClient->FetchFromPhoneBookL(EAiwPhoneNumberSelect); + ret = ETrue; + break; + case CMIDEdwinUtils::EMenuCommandFetchEmailAddress: + // for fetching data from phonebook + if (!iAiwPbkClient) + { + iAiwPbkClient = CMIDAiwPbk2Client::NewL(*this); + } + iAiwPbkClient->FetchFromPhoneBookL(EAiwEMailSelect); + ret = ETrue; + break; + case CMIDEdwinUtils::EMenuCommandCreatePhoneCall: + CreatePhoneCallL(); + ret = ETrue; + break; + default: + break; + } + + return ret; +} + +void CMIDTextBoxQueryDialog::DeleteTextL(TInt aOffset,TInt aLength) +{ + // get all initial values before deletion + TInt oldSize = Size(); + HBufC* oldText = iEditor->GetTextInHBufL(); + CleanupStack::PushL(oldText); + + TInt cursorPos = GetCaretPosition(); + + TCursorSelection selection = TCursorSelection(aOffset, aOffset + aLength); + _LIT(KEmptyText, ""); + iEditor->InsertDeleteCharsL(aOffset, KEmptyText, selection); + + // Check that new content is valid. + // If not, return old content and throw exception. + TBool valid = iEdwinUtils->ConstraintsValidForText(Read(), iConstraints, ETrue); + if (!valid) + { + iEditor->SetTextL(oldText); + } + CleanupStack::PopAndDestroy(oldText); + + iEditor->HandleTextChangedL(); + + if (!valid) + { + User::Leave(KErrArgument); + } + + // Handle cursor moving + + // Cursor is in the middle of delete area + if ((cursorPos > aOffset) && (cursorPos < (aOffset + aLength))) + { + SetCursorPositionL(aOffset); + } + // cursor is on the right side of delete area + else if (cursorPos > (aOffset + aLength)) + { + TInt newPosition = cursorPos - aLength; + if (newPosition < 0) + { + newPosition = 0; + } + SetCursorPositionL(newPosition); + } + // cursor is on the left side of delete area + else + { + SetCursorPositionL(cursorPos); + } +} + +void CMIDTextBoxQueryDialog::SetTextL(const TDesC& aText) +{ + // if text is invalid according to constraints, throw IllegalArgumentException, + // except for a PHONENUMBER which only has the invalid characters removed + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) + { + } + else if (!iEdwinUtils->ConstraintsValidForText(aText, iConstraints, ETrue)) + { + User::Leave(KErrArgument); + } + // + + HBufC* buf = iEdwinUtils->ConvertToLocalizedLC(aText, iConstraints); + + if (IsNumberConversionNeeded()) + { + TPtr ptr = buf->Des(); + AknTextUtils::LanguageSpecificNumberConversion(ptr); + } + + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) + { + iEdwinUtils->RemoveNonPhoneNumberChars(buf); + } + iEditor->SetTextL(buf); + iEditor->HandleTextChangedL(); + CleanupStack::PopAndDestroy(buf); + + // move cursor to end of the new text + SetCursorPositionL(Size()); +} + +void CMIDTextBoxQueryDialog::InsertTextL(const TDesC& aText,TInt aPosition) +{ + //VALIDATE EXISTING TEXT + HBufC* temp = NULL; + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal) + { + // Convert decimal content to unlocalized form before testing validity + // of insertion. + temp = GetTextL(); + if (temp) + { + CleanupStack::PushL(temp); + iEdwinUtils->ConvertFromLocalizedDecimal(temp); + } + } + + if (aPosition < 0) + aPosition = 0; + // + TInt size = Size(); + if (aPosition > size) + aPosition = size; + // + if (!iEdwinUtils->ConstraintsValidForInsertedTextL((temp ? temp->Des() : Read()), + aText, + aPosition, + iConstraints, + ETrue)) + User::Leave(KErrArgument); + if (temp) + { + CleanupStack::PopAndDestroy(temp); + temp = NULL; + } + // + //TEXT INSERTION STARTS HERE + if (IsReadyToDraw()) + { + iEditor->ClearSelectionL(); + } + + temp = iEdwinUtils->ConvertToLocalizedLC(aText, iConstraints); + + + if (IsNumberConversionNeeded()) + { + TPtr ptr = temp->Des(); + AknTextUtils::LanguageSpecificNumberConversion(ptr); + } + iEditor->Text()->InsertL(aPosition, temp->Des()); + + iEditor->HandleTextChangedL(); + + // Get the cursor position and move it forward along with inserter characters, if + // characters were inserted on the left side of the cursor. + TInt cursorPos = GetCaretPosition(); + TInt numberOfAddedCharacters = Size() - size; + + if (cursorPos >= aPosition) + { + if ((cursorPos + numberOfAddedCharacters) < iMaxSize) + { + SetCursorPositionL(cursorPos + numberOfAddedCharacters); + } + } + + CleanupStack::PopAndDestroy(temp); +} + +void CMIDTextBoxQueryDialog::SetConstraintsL(TUint /*aConstraints*/) +{ +} + +void CMIDTextBoxQueryDialog::SetFEPModeAndCharFormat() +{ + iEdwinUtils->SetFEPModeAndCharFormat(iConstraints, iEditor); +} + +TInt CMIDTextBoxQueryDialog::SetMaxSizeL(TInt aSize) +{ + TInt oldSize = Size(); + if (aSize < oldSize) + { + DeleteTextL(aSize, oldSize - aSize); + } + iMaxSize = aSize; + iEditor->SetTextLimit(iMaxSize); + iMaxSize = GetMaxSize(); + return iMaxSize; +} + +TInt CMIDTextBoxQueryDialog::GetMaxSize() +{ + return iEditor->MaxLength(); +} + +TInt CMIDTextBoxQueryDialog::Size() +{ + return iEditor->TextLength(); +} + +TInt CMIDTextBoxQueryDialog::GetCaretPosition() +{ + return iEditor->CursorPos(); +} + +HBufC* CMIDTextBoxQueryDialog::GetTextL() +{ + // getting of native text + HBufC* buf = iEditor->GetTextInHBufL(); + + // If there is no text in iEditor, this set empty buf. + if (!buf) + { + buf = HBufC::NewL(0); + } + + // convert decimal from localized to MIDlet-visible representation + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal) + { + iEdwinUtils->ConvertFromLocalizedDecimal(buf); + } + + // convert digits, if needed + if (IsNumberConversionNeeded()) + { + TPtr ptr = buf->Des(); + AknTextUtils::ConvertDigitsTo(ptr, EDigitTypeWestern); + } + + // Return a copy of the contents where newlines etc. are + // mapped to their Java representations. + CMIDUtils::MapETextToJavaChars(buf); + + + return buf; +} + +void CMIDTextBoxQueryDialog::SetInitialInputModeL(const TDesC& aCharacterSubset) +{ + iEdwinUtils->SetInitialInputModeL(aCharacterSubset, + iConstraints, + iInitialCurrentCase, + iInitialCurrentInputMode, + iInitialCurrentLanguage); + + TUint constraint = iConstraints & MMIDTextField::EConstraintMask; + + // Set permitted case modes for TextBox in lowercase or uppercase mode. + if (aCharacterSubset.Compare(KMidpUppercaseLatin) == 0 || + aCharacterSubset.Compare(KMidpLowercaseLatin) == 0) + { + // MIDP_UPPERCASE_LATIN or MIDP_LOWERCASE_LATIN are ignored if + // INITIAL_CAPS_SENTENCE or INITIAL_CAPS_WORD modifier in ANY. + if (!(iConstraints & MMIDTextField::EInitialCapsWordSentence || + iConstraints & MMIDTextField::EInitialCapsWord) || + constraint != MMIDTextField::EAny) + { + // If initial input mode is uppercase or lowercase then permit + // only explicit case mode changes, automatic changes are not + // allowed. + iEditor->SetAknEditorPermittedCaseModes(EAknEditorUpperCase | + EAknEditorLowerCase); + } + } + else + { + iEditor->SetAknEditorPermittedCaseModes(EAknEditorAllCaseModes); + } +} + +void CMIDTextBoxQueryDialog::SetTitleL(const TDesC* aString) +{ + if (aString) + { + SetPromptL(*aString); + } + else + { + SetPromptL(KNullDesC); + } +} + +void CMIDTextBoxQueryDialog::SetCursorPositionL(TInt aPosition) +{ + TInt textLength = iEditor->TextLength(); + if (textLength < aPosition) + { + aPosition = textLength; + } + if (textLength >0) + { + iEditor->SetCursorPosL(aPosition, EFalse); + } + else + { + iEditor->SetCursorPosL(0, EFalse); + } +} + +TSize CMIDTextBoxQueryDialog::ContentSize() const +{ + return CCoeControl::Size(); +} + +void CMIDTextBoxQueryDialog::FocusChanged(TDrawNow aDrawNow) +{ + CAknTextQueryDialog::FocusChanged(aDrawNow); + TBool isFocused = IsFocused(); +} +// +// We do not want to become visible if we are not showing +// +void CMIDTextBoxQueryDialog::MakeVisible(TBool aVisible) +{ + if (!aVisible) + { + CAknTextQueryDialog::MakeVisible(aVisible); + } + else if (iShowing) + { + if (aVisible) + { + //re-layouting done just before dialog is shown + //to be sure layout is correct in CAknPopupForm + CAknTextQueryDialog::SizeChanged(); + } + CAknTextQueryDialog::MakeVisible(aVisible); + } +} + +void CMIDTextBoxQueryDialog::SizeChanged() +{ + if (iShowing) + { + CAknTextQueryDialog::SizeChanged(); + } +} + +TKeyResponse CMIDTextBoxQueryDialog::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) +{ + // If midlet is closed from applications menu or by pressing end key, then + // 'esc' key event is generated. That event is not handled here. + // See OfferKeyEventL function of CMIDTextBoxDialogControl. + if (aKeyEvent.iCode == EKeyEscape) + { + return EKeyWasNotConsumed; + } + // + // Enter Key: + // + // + if (aType == EEventKey) + { + iusedKeyEvent = &aKeyEvent; + } + + // If TextBox have constraints below params + // Any and Password + // Numeric or Numeric and Password or + // Decimal or Decimal and Password or + // PhoneNumber or PhoneNumber and Password or + // MailAddr or MailAddr and Password or + // PhoneNumber Uneditable or MailAddr Uneditable or + // Url or Url and Password + // then show menu or activate one command. + if (((aType == EEventKey && aKeyEvent.iCode == EKeyEnter) || + (aType == EEventKeyUp && aKeyEvent.iScanCode == EStdKeyEnter && + aKeyEvent.iCode == EKeyEnter && iusedKeyEvent!=&aKeyEvent))) + { + + if ((iConstraints == MMIDTextField::EAny + MMIDTextField::EPassword) || + + (iConstraints == MMIDTextField::ENumeric || + (iConstraints == MMIDTextField::ENumeric + MMIDTextField::EPassword) || + iConstraints == MMIDTextField::EDecimal || + (iConstraints == MMIDTextField::EDecimal + MMIDTextField::EPassword)) || + + (iConstraints == MMIDTextField::EPhoneNumber || + (iConstraints == MMIDTextField::EPhoneNumber + MMIDTextField::EPassword) || + iConstraints == MMIDTextField::EMailAddr || + (iConstraints == MMIDTextField::EMailAddr + MMIDTextField::EPassword)) || + + ((iConstraints == MMIDTextField::EPhoneNumber + MMIDTextField::EUneditable) || + (iConstraints == MMIDTextField::EMailAddr + MMIDTextField::EUneditable)) || + + (iConstraints == MMIDTextField::EUrl || + (iConstraints == MMIDTextField::EUrl + MMIDTextField::EPassword))) + { + + // counter OK and Item elements from options menu + TInt numOpt = iDisplayable->NumCommandsForOkOptionsMenu(); + + //open menu + if (numOpt > 1) + { + iDisplayable->MenuHandler()->ShowMenuL(CMIDMenuHandler::EOkMenu); + } + else + { + CMIDCommand* cmdTmp = NULL; + + // counter of all elements from options menu + TInt numItemCommands = iDisplayable->MainCommandList()->Count(); + + for (TInt i = 0; i < numItemCommands; i++) + { + // for each command from menu + // count offset index only for commands + // without FetchPhoneNumber, EmailAddress, PhoneCall + cmdTmp = iDisplayable->MainCommandList()->At(i).iCommand; + + if (cmdTmp) + { + if ((cmdTmp->Id() != CMIDEdwinUtils::EMenuCommandFetchPhoneNumber) && + (cmdTmp->Id() != CMIDEdwinUtils::EMenuCommandFetchEmailAddress) && + (cmdTmp->Id() != CMIDEdwinUtils::EMenuCommandCreatePhoneCall)) + { + break; + } + } + } + + // execute command + if (cmdTmp) + { + if ((cmdTmp->CommandType() == MMIDCommand::EOk || + cmdTmp->CommandType() == MMIDCommand::EItem || + cmdTmp->CommandType() == MMIDCommand::EScreen)) + { + // get command index from option menu + TInt offsetIdx = iDisplayable->MainCommandList()->FindCommandIndex(cmdTmp); + + if (offsetIdx != KErrNotFound && + iDisplayable->MainCommandList()->At(offsetIdx).iCommand == cmdTmp) + { + iDisplayable->ProcessCommandL(iDisplayable->MainCommandList()->CommandOffset() + offsetIdx); + } + + } + } + } + return EKeyWasConsumed; + } + } + + // + // End Enter Key + // + + + // msk: this is needed if MSK is not enabled on the device + if ((aType == EEventKey) && (aKeyEvent.iScanCode == EStdKeyDevice3)) + { + iDisplayable->ShowOkOptionsMenuL(); + return EKeyWasConsumed; + } + + + // msk: this is needed if MSK is not enabled on the device + if ((aType == EEventKey) && (aKeyEvent.iScanCode == EStdKeyDevice3)) + { + iDisplayable->ShowOkOptionsMenuL(); + return EKeyWasConsumed; + } + + // store the key pressed last time, used for warning beeps while reaching size limit + if (aType == EEventKeyDown) + { + iLastMultitapKey = iThisMultitapKey; + iThisMultitapKey = aKeyEvent.iScanCode; + } + + if (aType == EEventKeyDown) + { + iKeyEventsPending = ETrue; + } + else if (aType == EEventKeyUp) + { + iKeyEventsPending = EFalse; + } + // + // Post ItemStateChangedEvent before a command is delivered to the Form's CommandListener + // + TUint scanCode = aKeyEvent.iScanCode; + + // + // ignore up and down arrows on PASSWORD TextField to avoid funny behaviour + // with line breaks + if (iDisplayable && (iConstraints & MMIDTextField::EPassword) + && (aKeyEvent.iCode == EKeyDownArrow || aKeyEvent.iCode == EKeyUpArrow)) + { + return EKeyWasConsumed; + } + + // when pressing the send key on a phonenumber-type box, call the number +#ifdef RD_SCALABLE_UI_V2 + if ((aType == EEventKey) && (scanCode == EStdKeyYes)) +#else + if ((aType == EEventKeyUp) && (scanCode == EStdKeyYes)) +#endif // RD_SCALABLE_UI_V2 + { + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) + { + CreatePhoneCallL(); + return EKeyWasConsumed; + } + } + +#ifdef RD_SCALABLE_UI_V2 + if (IsConstraintSet(MMIDTextField::ENumeric) && (aType == EEventKey || aType == EEventKeyUp) && !iEditor->IsReadOnly() && +#else + if (IsConstraintSet(MMIDTextField::ENumeric) && (aType == EEventKeyUp) && !iEditor->IsReadOnly() && +#endif // RD_SCALABLE_UI_V2 + ((scanCode==EStdKeyNkpAsterisk) || (scanCode == EStdKeyMinus) || (scanCode==EStdKeyNkpMinus) || (scanCode == 0x2A) || (scanCode == 0x2D))) + { + HandleMinusCharEventL(MEikEdwinObserver::EEventTextUpdate); + return EKeyWasConsumed; + } + + //handling of qwerty keypad "-" or "." pressing in Decimal mode +#ifdef RD_SCALABLE_UI_V2 + if (IsConstraintSet(MMIDTextField::EDecimal) && (aType == EEventKey) && !iEditor->IsReadOnly() && +#else + if (IsConstraintSet(MMIDTextField::EDecimal) && (aType == EEventKeyUp) && !iEditor->IsReadOnly() && +#endif // RD_SCALABLE_UI_V2 + ((scanCode==EStdKeyMinus) || (scanCode==EStdKeyFullStop))) + { + CPlainText* res = iEditor->Text(); + TInt textLength = Size(); + if (scanCode == EStdKeyMinus) + { + res->InsertL(GetCaretPosition(), KMinusChar); + } + else if (scanCode == EStdKeyFullStop) + { + res->InsertL(GetCaretPosition(), KFullStopChar); + } + + iEditor->HandleTextChangedL(); // notify editor about the text changes + + if (Size() < iMaxSize) + { + SetCursorPositionL(GetCaretPosition() + 1); + } + } + //Error tone playing case1: + //Play error tone if TextBox/TextField is read-only or maximum length has been reached. + //Here is handling of keys 0...9 for full keyboard and itu-t, but NOT virtual keyboard. + if (aType == EEventKeyDown + && ((scanCode >= KKeyQwerty0 && scanCode <= KKeyQwerty9) + || scanCode == EStdKeyHash + || scanCode == EStdKeyNkpAsterisk + || scanCode == KMidpKeyNkpAsteriskHW)) + { + if ((scanCode == EStdKeyNkpAsterisk || scanCode == KMidpKeyNkpAsteriskHW) + && !iEditor->IsReadOnly() && IsConstraintSet(MMIDTextField::ENumeric)) + { + //Do nothing here in case of minus char toggle + } + else if (iEditor->IsReadOnly()) + { + iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone); + return EKeyWasConsumed; + } + + // All possible sources of warning beep are separated to be easy to read + else if (Size() >= iMaxSize) + { + TInt ret = KErrNone; + TInt inputModeValue = iEditor->AknEditorCurrentInputMode(); + if (inputModeValue != EAknEditorTextInputMode) + { + iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone); + return EKeyWasConsumed; + } + + TInt aknRepositoryValue = 0; + CRepository* aknFepRepository = NULL; + TRAP(ret, aknFepRepository = CRepository::NewL(KCRUidAknFep)); + if ((ret != KErrNone) || (!aknFepRepository)) + { + // if we cannot get the repository (something is wrong), play nothing + return EKeyWasConsumed; + } + aknFepRepository->Get(KAknFepPredTxtFlag, aknRepositoryValue); + + delete aknFepRepository; + aknFepRepository = NULL; + + if (aknRepositoryValue == 1) // 1 means the predictive input is on + { + iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone); + return EKeyWasConsumed; + } + // now only nonpredictive textinput is left + if (iThisMultitapKey != iLastMultitapKey) // different key tapped -> no multitap + { + iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone); + iThisMultitapKey = 0; + iLastMultitapKey = 0; + return EKeyWasConsumed; + } + } + } + + if (aType != EEventKey) + { + return EKeyWasConsumed; + } + + + TKeyResponse response = EKeyWasNotConsumed; + + //Error tone playing case2: + //Play error tone if TextBox/TextField is read-only or maximum length has been reached. + //Here is handling of full keyboard keys(NOT 0...9) and all virtual keyboard keys. + //(Note: Virtual keyboard sends only EEventKey type events, not up or down events) + //(Note: Error tone is played when there is no text to be replaced i.e. no text has been painted) + if (!iEdwinUtils->IsNavigationKey(aKeyEvent) && !iEdwinUtils->IsHotKeyL(aKeyEvent, iCoeEnv) && !aKeyEvent.iCode == EKeyYes && + (!iKeyEventsPending || (scanCode < KKeyQwerty0 || scanCode > KKeyQwerty9))) + { + if (iEditor->IsReadOnly() || (Size() >= iMaxSize && aKeyEvent.iCode != EKeyBackspace)) + { + //SelectionLength() > 0 if text has been selected/painted + if (iEditor->SelectionLength() == 0) + { + iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone); + } + response = iEditor->OfferKeyEventL(aKeyEvent,aType); + return response; + } + } + + TBool valid = EFalse; + + if (iEdwinUtils->IsNavigationKey(aKeyEvent) || iEdwinUtils->IsHotKeyL(aKeyEvent, iCoeEnv)) + { + HBufC* oldText = GetTextL(); + CleanupStack::PushL(oldText); + TCursorSelection sel = iEditor->Selection(); + + response = CAknTextQueryDialog::OfferKeyEventL(aKeyEvent,aType); + valid = iEdwinUtils->ConstraintsValidForText(iEditor->Text()?Read():TPtrC(),iConstraints,EFalse); + + if (!valid) + { + SetTextL(*oldText); + iEditor->HandleTextChangedL(); + iEditor->SetSelectionL(sel.iCursorPos,sel.iAnchorPos); + response = EKeyWasConsumed; + } + CleanupStack::PopAndDestroy(oldText); + + return response; + } + else + { + TBuf<1> key; + key.Append(TChar(aKeyEvent.iCode)); + valid = iEdwinUtils->ConstraintsValidForInsertedTextL(iEditor->Text()?Read():TPtrC(), + key, + GetCaretPosition(), + iConstraints, + EFalse); + if (valid) + { + response = iEditor->OfferKeyEventL(aKeyEvent,aType); + } + return response; + } +} + +#ifdef RD_SCALABLE_UI_V2 +void CMIDTextBoxQueryDialog::HandlePointerEventL(const TPointerEvent &aPointerEvent) +{ + if (AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition)) + { + TBool consumed = STATIC_CAST(CMIDDisplayable*, iDisplayable)->TryDetectLongTapL(aPointerEvent); + if (!consumed) + { + CAknTextQueryDialog::HandlePointerEventL(aPointerEvent); + } + } +} +#endif // RD_SCALABLE_UI_V2 + +TCoeInputCapabilities CMIDTextBoxQueryDialog::InputCapabilities() const +{ + TCoeInputCapabilities inputCapabilities(TCoeInputCapabilities::ENone, NULL, + const_cast(this)); + inputCapabilities.MergeWith(iEditor->InputCapabilities()); + return inputCapabilities; +} + +void CMIDTextBoxQueryDialog::HandleEdwinEventL(CEikEdwin* aEdwin, TEdwinEvent aEventType) +{ + if (aEdwin != iEditor) + { + return; + } + + if (aEventType == MEikEdwinObserver::EEventTextUpdate) + { + // handles clearing multitap counter + if ((iLastMultitapKey != 0) && (iLastMultitapKey != iThisMultitapKey)) + { + iLastMultitapKey = 0; + } + else + { + iThisMultitapKey = 0; + iLastMultitapKey = 0; + } + + TBool textChanged = EFalse; + HBufC* res = NULL; + TRAPD(err, { res = GetTextL();}); + if (err != KErrNone || !res) + { + return; + } + CleanupStack::PushL(res); + + // in DECIMAL mode, don't allow changes that would result + // in an illegal string; + // 1) if there is a minus, it must be the first character + // 2) there can be at most one decimal separator + if ((aEventType == EEventTextUpdate) && ((iConstraints + & MMIDTextField::EConstraintMask) == MMIDTextField::EDecimal)) + { + TInt illegalCharPos = -1; + TPtr16 ptr = res->Des(); + TInt minusPos = ptr.LocateReverse(TChar('-')); + + // check if minus sign is inserted on incorrect place + // (not at the beginning) + if ((minusPos != KErrNotFound) && (minusPos != 0)) + { + // check if minus sign isn't inserted twice + if (minusPos != ptr.Locate(TChar('-'))) + { + illegalCharPos = minusPos; + } + // insert minus char at the beginning of decimal field + else + { + ptr.Delete(minusPos, 1); + ptr.Insert(0, KMinusChar); + minusPos = 0; + SetTextL(*res); + textChanged = ETrue; + } + } + + TInt pointPosL = ptr.Locate(iDecimalSeparator); + TInt pointPosR = ptr.LocateReverse(iDecimalSeparator); + TInt cursorPos = GetCaretPosition(); + if ((minusPos != KErrNotFound) && (pointPosL == 0)) + { + illegalCharPos = pointPosL; + } + else if (pointPosL != pointPosR) + { + illegalCharPos = pointPosR; + } + + // if minus or dot/comma char is displayed more than once + if (illegalCharPos >= 0) + { + // deleting second minus or dot/comma char + // and set cursor position on the right place + ptr.Delete(illegalCharPos, 1); + SetTextL(*res); + textChanged = ETrue; + if (cursorPos >= 1) + { + if (cursorPos == illegalCharPos) + { + cursorPos--; + } + SetCursorPositionL(cursorPos); + } + } + } + else if (((iConstraints & + MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr) || + ((iConstraints & + MMIDTextField::EConstraintMask) == MMIDTextField::EUrl)) + { + // In EMAIL and URL mode, don't allow changes that would result + // in an illegal string; if there is '/n' or '/f', and line breaks + // are not supported, chars need to be changed to space + // SetText function before actual text change checks if line + // breaks are not supported + SetTextL(*res); + textChanged = ETrue; + } + CleanupStack::Pop(res); + delete res; + + // if there were any modifications the text is updated + if (textChanged) + { + iEditor->HandleTextChangedL(); + } + } +} + +void CMIDTextBoxQueryDialog::GetCaptionForFep(TDes& aCaption) const +{ + aCaption = Prompt(); +} + +void CMIDTextBoxQueryDialog::ProcessModifiers() +{ + // set general edwin attributes according to TextBox constraints + iEditor->SetReadOnly(iConstraints & MMIDTextField::EUneditable); +} + +void CMIDTextBoxQueryDialog::ShowL(TBool aShow) +{ + if (aShow != iShowing) + { + if (aShow) + { + iShowing = ETrue; + +#ifdef RD_SCALABLE_UI_V2 + SetPointerCapture(ETrue); +#endif + RouseSleepingDialog(); + + UpdateInitialInputModes(); + } + else + { + ExitSleepingDialog(); +#ifdef RD_SCALABLE_UI_V2 + SetPointerCapture(EFalse); +#endif + + iShowing = EFalse; //attention: iShowing must be true when dismissing + // a dialog or else MakeVisible() won't execute and + // we won't update the fader's stack, @see MakeVisible() + + } + + UpdateCbasL(); + } +} + +void CMIDTextBoxQueryDialog::SetTextWithNewConstraintsL(HBufC* aText) +{ + // If the current contents of the TextBox do not match the new constraints,the + // contents are set to empty, except for a PHONENUMBER which only has the + // invalid characters removed. Otherwise, set the text as given. + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) + { + iEdwinUtils->RemoveNonPhoneNumberChars(aText); + SetTextL(*aText); + } + else if (!iEdwinUtils->ConstraintsValidForText(aText->Des(), + iConstraints & MMIDTextField::EConstraintMask, + ETrue)) + { + SetTextL(KNullDesC); + } + else + { + SetTextL(*aText); + } +} + +void CMIDTextBoxQueryDialog::UpdateLeftSoftKeyL() +{ +} + +TBool CMIDTextBoxQueryDialog::OkToExitL(TInt aCommandId) +{ + TInt offset = iDisplayable->MainCommandList()->CommandOffset(); + if (aCommandId ==EEikBidCancel) + { + return ETrue; + } + if (aCommandId == EAknSoftkeyOptions) // 3000 + { + iDisplayable->MenuHandler()->ProcessCommandL(EAknSoftkeyOptions); + SetFocus(EFalse); + } + else if (aCommandId - offset < 0) // aCommandId value is over 3000 - used by MSK + { + iDisplayable->ProcessCommandL(aCommandId); + } + else // aCommandId value is 7000 and over - used by LSK, RSK and EnterKey + { + CMIDCommand* tempCmd = NULL; + CMIDCommand* command = NULL; + TBool isMaped = EFalse; + TInt mapedCnt = ENone; + TInt mapedId = ENone; + + // number of all commands + TInt numberOfCommands = iDisplayable->CommandCount(); + // number of Ok and Item commands + TInt numberOfOkOptionsCommands = iDisplayable->NumCommandsForOkOptionsMenu(); + // command ID which is get from aCommandId + TInt commandId = aCommandId - offset; + + if (numberOfCommands > 0) + { + // Go through every midlet command, and save its ID if maped + // and also count maped commands. + for (TInt i = 0; i < numberOfCommands; i++) + { + tempCmd = iDisplayable->MainCommandList()->At(i).iCommand; + if (tempCmd->IsMappedToSoftKey()) + { + mapedId = i; + isMaped = ETrue; + mapedCnt++; + } + } + + // If there are more than one maped command (LSK & RSK maped) + // or maped command is different than commandId (EnterKey used), + // set CMIDCommand command with this command, which index + // is the same as commandId value. + if (mapedCnt > 1 || mapedId != commandId) + { + command = iDisplayable->MainCommandList()->At(commandId).iCommand; + } + else // Else if there are one or zero command maped. + { + if (isMaped) // One command maped. + { + command = iDisplayable->MainCommandList()->At(mapedId).iCommand; + } + else // Zero commands maped. + { + command = iDisplayable->MainCommandList()->At(0).iCommand; + } + } + + // type of the command + TInt commandType = command->CommandType(); + + // If there aren't any EExit, EBack, ECancel and EStop + // command mapped and there are still some commands + // show menu, else process with maped command. + if (commandType != MMIDCommand::EExit && + commandType != MMIDCommand::EBack && + commandType != MMIDCommand::ECancel && + commandType != MMIDCommand::EStop && + numberOfOkOptionsCommands > 1) + { + iDisplayable->MenuHandler()->ShowMenuL(CMIDMenuHandler::EOkMenu); + } + else + { + iDisplayable->ProcessCommandL(aCommandId); + } + } + } + + //The dialog can only be dismissed java side or else we'll end + //up with the TextBox displayed and no dialog + return EFalse; +} + +void CMIDTextBoxQueryDialog::SetEditorL() +{ + iEditor = (CEikEdwin*)QueryControl()->ControlByLayoutOrNull(EDataLayout); + iEditor->SetAknEditorFlags(CEikEdwin::EZeroEnumValue); + + TBool singleLineEditor = IsConstraintSet(MMIDTextField::EMailAddr) + || IsConstraintSet(MMIDTextField::EUrl) + || (iConstraints & MMIDTextField::EPassword); + + if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EAny) + && !(iConstraints & MMIDTextField::EPassword)) + { + iEditor->SetAknEditorFlags(EAknEditorFlagEnableScrollBars | iEditor->AknEdwinFlags()); + } + + AknEditUtils::ConstructEditingL(iEditor, // aEdwin + iMaxSize, // aEditingSpace + (singleLineEditor ? 1 : 0), // aEditingWindow + EAknEditorCharactersLowerCase, // aCharacterCase + EAknEditorAlignLeft, // aJustification + ETrue, // aAllowedToMoveInsertionPoint + ETrue, // aCursorYesNo + EFalse); // aOverflowYesNo + + + if (iConstraints & MMIDTextField::EPassword) + { + TUint32 userFlags = iEditor->UserFlags(); + iEditor->SetAknEditorFlags(userFlags |= CEikEdwin::EUserSuppliedText); + CreatePasswordTextL(); + } + + HBufC* buf = GetTextL(); + CleanupStack::PushL(buf); + if (buf) + { + CMIDUtils::MapJavaToETextChars(buf); + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) + { + iEdwinUtils->RemoveNonPhoneNumberChars(buf); + } + SetTextL(*buf); + } + CleanupStack::PopAndDestroy(buf); + + iEditor->CreateTextViewL(); + ProcessModifiers(); + SetFEPModeAndCharFormat(); + iEditor->AddEdwinObserverL(this); + + CreateNonMidletCommandsL(); + + if ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::ENonPredictive) + { + SetPredictiveTextInputPermitted(EFalse); + } + else + { + SetPredictiveTextInputPermitted(ETrue); + } + // Publish MIDP constraints via input capabilities of the CEikEdwin + // The information is needed by chinese VKB/HWR system that adjusts its behavior + // based on MIDP constraints (most notably by checking if the field is a PASSWORD field). + TCoeInputCapabilities inputCapabilities = InputCapabilities(); + if (inputCapabilities != TCoeInputCapabilities::ENone) + { + MObjectProvider* mop = inputCapabilities.ObjectProvider(); + if (mop) + { + CAknExtendedInputCapabilities* extendedInputCapabilities = NULL; + extendedInputCapabilities = mop->MopGetObject(extendedInputCapabilities); + if (extendedInputCapabilities) + { + extendedInputCapabilities->SetMIDPConstraints(iConstraints); + } + } + } + + iThisMultitapKey = 0; // reset key counter + iLastMultitapKey = 0; +} + +TBool CMIDTextBoxQueryDialog::Showing() +{ + return iShowing; +} + +TInt CMIDTextBoxQueryDialog::Constraints() +{ + return iConstraints; +} + +void CMIDTextBoxQueryDialog::UpdateCbasL() +{ + if (iShowing) + { + iDisplayable->SetCba(&ButtonGroupContainer()); + iDisplayable->InitializeCbasL(); + CCoeControl* cba = ButtonGroupContainer().ButtonGroup()->AsControl(); + cba->DrawableWindow()->SetOrdinalPosition(0); + cba->MakeVisible(ETrue); + cba->DrawNow(); + } + else + { + iDisplayable->SetCba(iDisplayable->MenuHandler()->Cba()); + } +} + +TBool CMIDTextBoxQueryDialog::IsNumberConversionNeeded() +{ + return iEdwinUtils->IsNumberConversionNeeded(GetConstraints()); +} + +void CMIDTextBoxQueryDialog::HandleMinusCharEventL(MEikEdwinObserver::TEdwinEvent aEventType) +{ + if ((aEventType == MEikEdwinObserver::EEventTextUpdate) && ((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::ENumeric)) + { + CPlainText* res = iEditor->Text(); + TBuf<1> firstChar; + if (Size() != 0) + { + res->Extract(firstChar, 0, 1); + } + TInt cursorPos = GetCaretPosition(); + //toggle '-' char in the first position + TInt pos = firstChar.Locate(TChar('-')); + if (pos == KErrNotFound) + { + if (Size() < iMaxSize) + { + res->InsertL(0, KMinusChar); + cursorPos++; + } + else + { + //play error sound if text limit is to be exceeded + iAvkonAppUi->KeySounds()->PlaySound(EAvkonSIDErrorTone); + } + } + else + { + TBool deletion = res->DeleteL(0,1); + if (cursorPos >= 1) + { + cursorPos--; + } + } + iEditor->HandleTextChangedL(); // notify editor about the text changes + SetCursorPositionL(cursorPos); + } +} + +TPtrC CMIDTextBoxQueryDialog::Read() const +{ + if (iConstraints & MMIDTextField::EPassword) + { + return static_cast(iEditor->Text())->ClearText(); + } + else + { + return iEditor->Text()->Read(0,iEditor->TextLength()); + } +} + +/** Create non-midlet commands according to the constraints and add them +to either the displayable or to the item. Commands will be processed in ProcessCommandL(). */ +void CMIDTextBoxQueryDialog::CreateNonMidletCommandsL() +{ + RPointerArray array; + CleanupClosePushL(array); + + if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) && !(iConstraints & MMIDTextField::EUneditable)) + { + AddCommandToArrayL(array, R_MIDP_PB_FETCH_NUMBER_SHORT_COMMAND_TEXT, R_MIDP_PB_FETCH_NUMBER_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandFetchPhoneNumber); + AddCommandToArrayL(array, R_MIDP_CREATE_CALL_SHORT_COMMAND_TEXT, R_MIDP_CREATE_CALL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandCreatePhoneCall); + } + + if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EPhoneNumber) && (iConstraints & MMIDTextField::EUneditable)) + { + AddCommandToArrayL(array, R_MIDP_CREATE_CALL_SHORT_COMMAND_TEXT, R_MIDP_CREATE_CALL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandCreatePhoneCall); + } + + if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr) && !(iConstraints & MMIDTextField::EUneditable)) + { + AddCommandToArrayL(array, R_MIDP_PB_FETCH_EMAIL_SHORT_COMMAND_TEXT, R_MIDP_PB_FETCH_EMAIL_COMMAND_TEXT, CMIDEdwinUtils::EMenuCommandFetchEmailAddress); + } + AddCommandsToEdwinL(array); + + CleanupStack::PopAndDestroy(&array); +} + +/** +Creates and adds new command to array based on shot & long label resource ids +and other parameters. +*/ +void CMIDTextBoxQueryDialog::AddCommandToArrayL(RPointerArray& aArray, + TInt aCommandResIdShort, TInt aCommandResIdLong, TInt aCommandId) +{ + TBuf<64> shortLabel; + iEikonEnv->ReadResourceL(shortLabel, aCommandResIdShort); + TBuf<64> longLabel; + iEikonEnv->ReadResourceL(longLabel, aCommandResIdLong); + + MMIDCommand* cmd = CMIDCommand::NewL(shortLabel, longLabel, MMIDCommand::EItem, 0, aCommandId); + CleanupStack::PushL(cmd); + + STATIC_CAST(CMIDCommand*,cmd)->SetObserver(this); + + aArray.AppendL(cmd); + CleanupStack::Pop(cmd); +} + +/** +Creates and adds new command to array, short label is the same as long label. +*/ +void CMIDTextBoxQueryDialog::AddCommandToArrayL(RPointerArray& aArray, + TInt aCommandResId, TInt aCommandId) +{ + AddCommandToArrayL(aArray, aCommandResId, aCommandResId, aCommandId); +} + +/** This method is called from the destructor and removes + the commands added by CreateNonMidletCommandsL(). To do + this we examine cmds on the list (either of the displayable + or the item as applicable) and remove those whose observer is us. + */ +void CMIDTextBoxQueryDialog::RemoveNonMidletCommands() +{ + CMIDCommandList* list = NULL; + if (iDisplayable) + { + list = STATIC_CAST(CMIDDisplayable*, iDisplayable)->MainCommandList(); + } + + if (!list) + { + return; + } + + for (TInt i = 0; i < list->Count(); i++) + { + CMIDCommand* cmd = list->At(i).iCommand; + if (cmd && (cmd->Observer() == this)) + { + list->Remove(cmd); + cmd->Dispose(); + i--; + } + } +} + +void CMIDTextBoxQueryDialog::AddCommandsToEdwinL(RPointerArray& aArray) +{ + for (TInt i = 0; i < aArray.Count(); i++) + { + STATIC_CAST(CMIDDisplayable*, iDisplayable)->AddCommandL(aArray[i]); + } +} + +void CMIDTextBoxQueryDialog::CreatePhoneCallL() +{ + iEdwinUtils->CreatePhoneCallL(Size(), CCoeEnv::Static()->WsSession(), iEditor); +} + +void CMIDTextBoxQueryDialog::CreatePasswordTextL() +{ + CGlobalText* oldGText = STATIC_CAST(CGlobalText*,iEditor->Text()); + CPasswordBoxGlobalText* text = new(ELeave) CPasswordBoxGlobalText + (oldGText->GlobalParaFormatLayer(),oldGText->GlobalCharFormatLayer(),*iEditor); + CleanupStack::PushL(text); + text->ConstructL(); + CleanupStack::Pop(text); + + CPlainText* editorText = iEditor->Text(); + delete editorText; + editorText = NULL; + + iEditor->SetDocumentContentL(*text,CEikEdwin::EUseText); +} + +void CMIDTextBoxQueryDialog::UpdateInitialInputModes() +{ + // when becoming the current Displayable, set editor input mode + // to the one set by SetInitialInputModeL + if (((iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EAny || + (iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EMailAddr || + (iConstraints & MMIDTextField::EConstraintMask) == MMIDTextField::EUrl)) + { + if (iInitialCurrentLanguage) + { + iEditor->SetAknEditorLocalLanguage(iInitialCurrentLanguage); + if (iInitialCurrentInputMode == 0) + { + // clears any number mode used previously + iEditor->SetAknEditorCurrentInputMode(EAknEditorNullInputMode); + } + } + + if (iInitialCurrentInputMode) + { + iEditor->SetAknEditorCurrentInputMode(iInitialCurrentInputMode); + } + + if (iInitialCurrentCase) + { + if ((iConstraints & MMIDTextField::EPassword || + iConstraints & MMIDTextField::EMailAddr || + iConstraints & MMIDTextField::EUrl) && + iInitialCurrentCase == EAknEditorTextCase) + { + // Text case is not used in passwords, emailaddrs and urls + iInitialCurrentCase = EAknEditorLowerCase; + } + iEditor->SetAknEditorCurrentCase(iInitialCurrentCase); + iEditor->SetAknEditorCase(iInitialCurrentCase); + } + } +} + +TTypeUid::Ptr CMIDTextBoxQueryDialog::MopSupplyObject(TTypeUid aId) +{ + if (aId.iUid == CEikMenuBar::ETypeId) + { + if (iDisplayable && iDisplayable->MenuHandler()) + { + return SupplyMopObject(aId, + iDisplayable->MenuHandler()->Cba(), + iDisplayable->MenuHandler()->MenuBar()); + } + } + return CAknTextQueryDialog::MopSupplyObject(aId); +} + +// End of file