--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/converter/Ui/Src/CCnvMainForm.cpp Mon Jan 18 20:20:33 2010 +0200
@@ -0,0 +1,1259 @@
+/*
+* Copyright (c) 2002 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:
+* This is the implementation of the class defined in CCnvMainForm.h
+*
+*/
+
+
+
+#include <barsread.h>
+#include <eikenv.h>
+#include <eikappui.h>
+#include <eikfpne.h>
+#include <avkon.hrh>
+#include <AknPopupField.h>
+#include <aknnotewrappers.h>
+#include <eikmenup.h>
+#include <s32file.h>
+#include <ErrorUI.h>
+#include <featmgr.h>
+
+#include <hlplch.h>
+#include <csxhelp/cnv.hlp.hrh>
+
+#include <CCnvConverter.h>
+#include <TCnvCategory.h>
+#include <Converter.rsg>
+#include "Converter.hrh"
+#include "CCnvApplication.h"
+#include "CCnvMainForm.h"
+#include "CCnvRatesForm.h"
+
+#include <aknnumed.h>
+#include <f32file.h>
+#include <e32std.h>
+
+_LIT( KCnvPlusSign, "+" );
+_LIT( KCnvMinusSign, "-" );
+_LIT( KCnvExponentSign, "E" );
+_LIT( KCnvDotSign, "." );
+
+_LIT( KCnvMinusInTheMiddle, "?*-?*" );
+_LIT( KCnvPlusInTheMiddle, "?*+?*" );
+_LIT( KCnvExponentInTheMiddle, "?*E?*" );
+_LIT( KCnvExponentInTheMiddleAndEnd, "?*E?*E?" );
+
+ _LIT( KConverterFilename,"UnitConverter.ini");
+ _LIT(KDelimiter, ":");
+
+CCnvMainForm::CCnvMainForm( TBool &aAlreadyDead )
+: iIsFullyConstructed( EFalse ),
+iHasNotifiedDiscFull( EFalse ),
+iLastUsedEditorId( EConverterEditor1 ),
+iHistoryTypeCategory( -1 ),
+iHistoryUnit1Category( -1 ),
+iHistoryUnit2Category( -1 ),
+iAlreadyDead( aAlreadyDead )
+ {
+ }
+
+CCnvMainForm::~CCnvMainForm()
+ {
+ if( iIsFullyConstructed )
+ {
+ SaveState();
+ }
+ delete iModel;
+ delete iConversionTimer;
+ delete iErrorUI;
+ iAlreadyDead = ETrue;
+
+ //remove the edwin observers
+ CEikFloatingPointEditor* editor1 =
+ static_cast< CEikFloatingPointEditor* >( Control( EConverterEditor1 ) );
+ editor1->RemoveEdwinObserver(this);
+
+ CEikFloatingPointEditor* editor2 =
+ static_cast< CEikFloatingPointEditor* >( Control( EConverterEditor2 ) );
+ editor2->RemoveEdwinObserver(this);
+
+ }
+
+void CCnvMainForm::ConstructL()
+ {
+ CAknDialog::ConstructL( R_CNV_MAINFORM_MENUBAR );
+
+ iErrorUI = CErrorUI::NewL( *iCoeEnv );
+
+ TResourceReader reader;
+ iEikonEnv->CreateResourceReaderLC( reader, R_CNV_MODEL );
+ iModel = CCnvConverter::NewL( reader );
+ CleanupStack::PopAndDestroy(); // reader
+
+ iConversionTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+
+ iCurrencyCategoryId = iModel->CurrencyCategoryId();
+ iIsFullyConstructed = ETrue;
+ isEdwinUpdateText = EFalse;
+
+ TFileName path;
+ iEikonEnv->FsSession().PrivatePath(path);
+ iEikonEnv->FsSession().MkDirAll(path);
+
+ }
+
+void CCnvMainForm::GetHelpContext( TCoeHelpContext& aContext ) const
+ {
+ aContext.iMajor = KUidCnv;
+ aContext.iContext = KCNV_HLP_MAIN_STATE;
+ }
+
+// Handle commands from Options menu
+void CCnvMainForm::ProcessCommandL( TInt aCommandId )
+ {
+ // this hides the options menu etc.
+ CAknForm::ProcessCommandL( aCommandId );
+
+ switch( aCommandId )
+ {
+ case ECmdSetType:
+ {
+ CmdSetTypeL();
+ break;
+ }
+
+ case ECmdSetUnit: // FLOWTHROUGH
+ case ECmdSetCurrency:
+ {
+ CmdSetUnitL();
+ break;
+ }
+
+ case ECmdRates:
+ {
+ CmdRatesL();
+ break;
+ }
+ case EAknCmdHelp:
+ {
+ iEikonEnv->EikAppUi()->HandleCommandL( EAknCmdHelp );
+ break;
+ }
+ case EEikCmdExit:
+ {
+ OkToExitL( EAknSoftkeyExit );
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+// Takes any action required when the current line is changed to aControlId.
+void CCnvMainForm::LineChangedL( TInt aControlId )
+ {
+
+ CEikButtonGroupContainer& cba = ButtonGroupContainer();
+ cba.SetCommandSetL(R_CNV_MAINFORM_SOFTKEYS);
+
+ if( ( aControlId == EConverterEditor1 ) ||
+ ( aControlId == EConverterEditor2 ) )
+ {
+ CEikFloatingPointEditor* editor =
+ static_cast< CEikFloatingPointEditor* >( Control( aControlId ) );
+
+ // don't clear the selection if there is only '0' in the editor
+ TBuf<KEditorTextMaxLength> editorText;
+ editor->GetText(editorText);
+
+ SynchronousConversionL();
+ // iActiveEditorChanged = EFalse;
+ }
+ else if(aControlId == EConverterUnit1Popup ||
+ aControlId == EConverterUnit2Popup)
+ {
+
+
+ // if focus is moved to unit popup from amount field
+ // then try to do the conversion.
+ // IsEditorValueValidL shows invalid value note if value is not valid
+ TBool editorValueValid = IsEditorValueValidL(iLastUsedEditorId);
+ if (editorValueValid && AreRatesValidL(ETrue))
+ {
+ SynchronousConversionL();
+ }
+ }
+ if(aControlId == EConverterUnit1Popup ||
+ aControlId == EConverterUnit2Popup ||
+ aControlId == EConverterTypePopup)
+ {
+ //Makes the MSK visible
+
+ cba.MakeCommandVisible(EAknSoftkeyChange,ETrue);
+
+
+ }
+ else if(aControlId ==EConverterEditor1 ||
+ aControlId ==EConverterEditor2)
+ {
+
+
+ //makes the MSK invisible
+
+ cba.MakeCommandVisible(EAknSoftkeyChange,EFalse);
+
+ }
+ cba.DrawNow();
+ }
+
+void CCnvMainForm::DynInitMenuPaneL( TInt aResourceId,
+ CEikMenuPane* aMenuPane )
+ {
+ // When click on LSK(option), the invalid value should be set to 0.
+ TInt controlId( IdOfFocusControl() );
+ if ( ( controlId == EConverterEditor1 ) || ( controlId == EConverterEditor2 ) )
+ {
+ if ( EditorValueCausesHold( controlId ) || !IsVaildNumberEntered( controlId ) )
+ {
+ SetFloatEditorValueL( controlId, 0.0 );
+ }
+ SynchronousConversionL( EFalse );
+ }
+
+ TUint currentType( iTypeCategory.CurrentValueIndex() );
+
+ if( aResourceId == R_CNV_MAINFORM_MENUPANE )
+ {
+ if (!FeatureManager::FeatureSupported(KFeatureIdHelp))
+ {
+ aMenuPane->SetItemDimmed(EAknCmdHelp, ETrue);
+ }
+
+ if( currentType == iCurrencyCategoryId )
+ {
+ aMenuPane->SetItemDimmed( ECmdRates, EFalse ) ;
+ }
+
+ switch( IdOfFocusControl() )
+ {
+ case EConverterUnit1Popup:
+ case EConverterUnit2Popup:
+ {
+ if( currentType == iCurrencyCategoryId )
+ {
+ aMenuPane->SetItemDimmed( ECmdSetCurrency, EFalse ) ;
+ }
+ else
+ {
+ aMenuPane->SetItemDimmed( ECmdSetUnit, EFalse ) ;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ }
+
+// Handles events to the three pop lists
+void CCnvMainForm::HandleControlEventL( CCoeControl* /*aControl*/,
+ TCoeEvent aEventType )
+ {
+ // We are interested only about EEventStateChanged events
+ if( aEventType != EEventStateChanged )
+ {
+ return;
+ }
+
+ TInt controlId( IdOfFocusControl() );
+
+ if( !HasReallyChanged( controlId ) )
+ {
+ return;
+ }
+
+ switch( controlId )
+ {
+ case EConverterTypePopup:
+ {
+ HandleCategoryChangedL();
+ break;
+ }
+ case EConverterUnit1Popup:
+ case EConverterUnit2Popup:
+ {
+ HandleUnitChangedL();
+ break;
+ }
+ //These have been moved to OfferKeyEventL
+ case EConverterEditor1:
+ case EConverterEditor2:
+ {
+ iLastUsedEditorId = controlId;
+ if( (iActiveEditorChanged)&&
+ ( isEdwinNavigated == EFalse || isEdwinUpdateText ) ) // Is there any navigation (or selection)
+ //happening on the editor
+ {
+ AsynchronousConversion();
+ }
+ isEdwinNavigated = EFalse; //make the boolean false
+ iActiveEditorChanged = ETrue;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+TBool CCnvMainForm::SaveFormData()
+ {
+ // Always allow exit (data is saved in the destructor)
+ return ETrue;
+ }
+
+TBool CCnvMainForm::OkToExitL( TInt aButtonId )
+ {
+ TBool status( CAknDialog::OkToExitL( aButtonId ) );
+ TInt controlId( IdOfFocusControl() );
+ if( status && ( aButtonId == EAknSoftkeyExit ) )
+ {
+ iEikonEnv->EikAppUi()->HandleCommandL( EAknCmdExit );
+ }
+ else if(aButtonId == EAknSoftkeyChange)
+ {
+ if (controlId == EConverterTypePopup)
+ {
+ CmdSetTypeL();
+ status = EFalse;
+ }
+ else if ((controlId == EConverterUnit1Popup) ||(controlId == EConverterUnit2Popup))
+ {
+ CmdSetUnitL();
+ status = EFalse;
+ }
+ }
+ else
+ {
+ status = EFalse;
+ }
+ return status;
+ }
+
+void CCnvMainForm::PreLayoutDynInitL()
+ {
+ // Store pointers to the popup list controls
+ // (makes further access easier/faster)
+ iTypePopupCtrl =
+ static_cast< CAknPopupField* >( Control( EConverterTypePopup ) );
+ iUnit1PopupCtrl =
+ static_cast< CAknPopupField* >( Control( EConverterUnit1Popup ) );
+ iUnit2PopupCtrl =
+ static_cast< CAknPopupField* >( Control( EConverterUnit2Popup ) );
+
+
+ // Set values for the unit category popup control
+ iModel->GetCategorylistAccessor( iTypeCategory );
+ iTypePopupCtrl->SetQueryValueL( &iTypeCategory );
+
+ // Load user selections from file (if any)
+ LoadStateL();
+
+ // Set initial values for the popup lists
+ HandleCategoryChangedL();
+
+ InitialiseChangeHistory();
+
+ if (iUnit1Category.UnitFactor(iUnit1Category.CurrentValueIndex()) != 0.0 &&
+ iUnit2Category.UnitFactor(iUnit2Category.CurrentValueIndex()) != 0.0)
+ {
+ SynchronousConversionL();
+ }
+
+ //Add wdwin observers for the two editors so that they can capture the Navigation
+ //events and not do asynchronous conversion
+ CEikFloatingPointEditor* editor1 =
+ static_cast< CEikFloatingPointEditor* >( Control( EConverterEditor1 ) );
+
+ CEikFloatingPointEditor* editor2 =
+ static_cast< CEikFloatingPointEditor* >( Control( EConverterEditor2 ) );
+
+ editor1->AddEdwinObserverL(this);
+ editor2->AddEdwinObserverL(this);
+
+
+ }
+
+TBool CCnvMainForm::HasReallyChanged( TInt controlId )
+ {
+ TBool changed( EFalse );
+
+ switch( controlId )
+ {
+ case EConverterTypePopup:
+ {
+ if( iTypeCategory.CurrentValueIndex() != iHistoryTypeCategory )
+ {
+ changed = ETrue;
+ iHistoryTypeCategory = iTypeCategory.CurrentValueIndex();
+
+ // renew iHistoryUnit1Category and iHistoryUnit2Category
+ iModel->GetCategoryAccessor( iUnit1Category, iHistoryTypeCategory );
+ TUint HistoryUnit1Category;
+ TUint HistoryUnit2Category;
+ iUnit1Category.GetDefaultUnits( HistoryUnit1Category , HistoryUnit2Category );
+ iHistoryUnit1Category = HistoryUnit1Category;
+ iHistoryUnit2Category = HistoryUnit2Category;
+ }
+ break;
+ }
+ case EConverterUnit1Popup:
+ {
+ if( iUnit1Category.CurrentValueIndex() != iHistoryUnit1Category )
+ {
+ changed = ETrue;
+ iHistoryUnit1Category = iUnit1Category.CurrentValueIndex();
+ }
+ break;
+ }
+ case EConverterUnit2Popup:
+ {
+ if( iUnit2Category.CurrentValueIndex() != iHistoryUnit2Category )
+ {
+ changed = ETrue;
+ iHistoryUnit2Category = iUnit2Category.CurrentValueIndex();
+ }
+ break;
+ }
+
+ case EConverterEditor1:
+ case EConverterEditor2:
+ {
+ changed = ETrue;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ return changed;
+ }
+
+void CCnvMainForm::InitialiseChangeHistory()
+ {
+ iHistoryTypeCategory = iTypeCategory.CurrentValueIndex();
+ iHistoryUnit1Category = iUnit1Category.CurrentValueIndex();
+ iHistoryUnit2Category = iUnit2Category.CurrentValueIndex();
+ }
+
+void CCnvMainForm::HandleCategoryChangedL()
+ {
+ TInt categoryId = iTypeCategory.CurrentValueIndex();
+ iModel->GetCategoryAccessor( iUnit1Category, categoryId );
+ iModel->GetCategoryAccessor( iUnit2Category, categoryId );
+
+ TUint srcUnit, dstUnit;
+ iUnit1Category.GetDefaultUnits( srcUnit, dstUnit );
+ iUnit1Category.SetCurrentValueIndex( srcUnit );
+ iUnit2Category.SetCurrentValueIndex( dstUnit );
+
+ // Set arrays to popup lists and redraw them
+ iUnit1PopupCtrl->SetQueryValueL( &iUnit1Category );
+ iUnit2PopupCtrl->SetQueryValueL( &iUnit2Category );
+ iUnit1PopupCtrl->DrawNow();
+ iUnit2PopupCtrl->DrawNow();
+
+ // Reset amount fields
+ TReal zero( 0.0 );
+ SetFloatingPointEditorValueL( EConverterEditor1, &zero );
+ SetFloatingPointEditorValueL( EConverterEditor2, &zero );
+
+ // when category's type is temperature the editor's value can't simply set to zero
+ AsynchronousConversion();
+
+ iLastUsedEditorId = EConverterEditor1;
+ }
+
+void CCnvMainForm::HandleUnitChangedL()
+ {
+ iUnit1Category.SetDefaultUnits( iUnit1Category.CurrentValueIndex(),
+ iUnit2Category.CurrentValueIndex() );
+ SynchronousConversionL();
+ }
+
+TBool CCnvMainForm::AreRatesValidL(TBool aShowNote)
+ {
+ TInt numInvalid( 0 );
+ if( iUnit1Category.UnitFactor( iUnit1Category.CurrentValueIndex() )
+ == 0.0 )
+ {
+ numInvalid++;
+ SetFloatEditorValueL( EConverterEditor1, 0.0 );
+ }
+ if( iUnit2Category.UnitFactor( iUnit2Category.CurrentValueIndex() )
+ == 0.0 )
+ {
+ numInvalid++;
+ SetFloatEditorValueL( EConverterEditor2, 0.0 );
+ }
+
+ if(numInvalid)
+ {
+ CancelConversion();
+
+ if (aShowNote)
+ {
+ TBool isPlural( EFalse );
+ if( numInvalid > 1 )
+ {
+ isPlural = ETrue;
+ }
+
+ TInt resourceId(R_CNV_MAINFORM_NORATE );
+ if( isPlural )
+ {
+ resourceId = R_CNV_MAINFORM_NORATE_PLURAL;
+ }
+ HBufC* label = iCoeEnv->AllocReadResourceLC( resourceId );
+ CAknErrorNote* note = new( ELeave ) CAknErrorNote;
+ note->ExecuteLD( *label );
+ CleanupStack::PopAndDestroy(); // label;
+ }
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+void CCnvMainForm::ShowInvalidValueNoteL(TInt aEditorId)
+ {
+ CancelConversion();
+
+ SetFloatEditorValueL( aEditorId, 0.0 );
+
+ HBufC* label = iCoeEnv->AllocReadResourceLC(
+ R_CNV_MAINFORM_INVALIDVALUE );
+ CAknErrorNote* note = new( ELeave ) CAknErrorNote;
+ note->ExecuteLD( *label );
+ CleanupStack::PopAndDestroy(); // label;
+
+ SynchronousConversionL();
+ }
+
+TBool CCnvMainForm::IsEditorValueValidL( TUint aEditorId )
+ {
+ TReal amount( FloatingPointEditorValue( aEditorId ) );
+
+ TReal minimum;
+ if( aEditorId == EConverterEditor1 )
+ {
+ minimum = iUnit1Category.UnitMinimum(
+ iUnit1Category.CurrentValueIndex() );
+ }
+ else
+ {
+ minimum = iUnit2Category.UnitMinimum(
+ iUnit2Category.CurrentValueIndex() );
+ }
+
+ if( amount < minimum )
+ {
+ ShowInvalidValueNoteL(aEditorId);
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+TBool CCnvMainForm::EditorValueCausesHold( TUint aEditorId )
+ {
+ CEikFloatingPointEditor* editor =
+ static_cast< CEikFloatingPointEditor* >( Control( aEditorId ) );
+
+ if( editor->TextLength() == 0 )
+ {
+ return ETrue;
+ }
+
+ TBuf< 12 > content;
+ TLocale locale;
+
+ // Not all the countries use '.' to express radix point, some use ','.
+ // So use locale.DecimalSeparator() to get local symbol.
+ TBuf<1> decimal;
+ decimal.Append( locale.DecimalSeparator() );
+ editor->Text()->Extract( content, 0, 12 );
+ TInt contentLength( content.Length() );
+ if ( !content.Compare( KCnvPlusSign ) )
+ {
+ return ETrue;
+ }
+ else if ( !content.Compare( KCnvMinusSign ) )
+ {
+ return ETrue;
+ }
+
+ else if ( !content.Compare( decimal ) )
+ {
+ return ETrue;
+ }
+ else if( contentLength > 1 &&
+ content[ contentLength - 1 ] == KCnvExponentSign()[ 0 ] &&
+ IsDigit( content[ contentLength - 2 ] ) &&
+ content.Match( KCnvExponentInTheMiddle ) == KErrNotFound &&
+ content.Match( KCnvMinusInTheMiddle ) == KErrNotFound &&
+ content.Match( KCnvPlusInTheMiddle ) == KErrNotFound)
+ {
+ // If content ends with <digit>E with no minus, plus or exponent
+ // sign in the middle
+ return ETrue;
+ }
+ else if( contentLength > 2 &&
+ ( content[ contentLength - 1 ] == KCnvMinusSign()[ 0 ] ||
+ content[ contentLength - 1 ] == KCnvPlusSign()[ 0 ] ) &&
+ content[ contentLength - 2 ] == KCnvExponentSign()[ 0 ] &&
+ IsDigit( content[ contentLength - 3 ] ) &&
+ content.Match( KCnvExponentInTheMiddleAndEnd ) == KErrNotFound &&
+ content.Match( KCnvMinusInTheMiddle ) == KErrNotFound &&
+ content.Match( KCnvPlusInTheMiddle ) == KErrNotFound )
+ {
+ // If content ends with <digit>E[+|-] with no minus, plus or exponent
+ // sign in the middle
+ return ETrue;
+ }
+ else if(contentLength > 12 &&
+ content.Locate(locale.DecimalSeparator()) == contentLength - 1)
+ {
+ // content ends with decimal separator and there is no other
+ // decimal separator
+ return ETrue;
+ }
+
+
+ return EFalse;
+ }
+
+void CCnvMainForm::CmdRatesL()
+ {
+ TBool wantsRelaunch;
+ TBool shouldExit( EFalse );
+ TBool needsSave( EFalse );
+ do
+ {
+ wantsRelaunch = EFalse;
+ TCnvCategory currencies;
+ iModel->GetCategoryAccessor( currencies, iCurrencyCategoryId );
+
+ CCnvRatesForm* rates = new( ELeave ) CCnvRatesForm( &wantsRelaunch,
+ &shouldExit, &needsSave, currencies);
+
+ CleanupStack::PushL( rates );
+ rates->ConstructL();
+ CleanupStack::Pop(); // rates
+ rates->ExecuteLD( R_CNV_RATESFORM );
+ }
+ while( wantsRelaunch );
+
+ if( needsSave )
+ {
+ SaveState();
+ }
+
+ if( !shouldExit )
+ {
+ // Reset the form (there might be changes in unit names..)
+ HandleCategoryChangedL();
+
+ DrawNow();
+ }
+ else
+ {
+ TryExitL( EAknSoftkeyExit );
+ }
+ }
+
+void CCnvMainForm::CmdSetTypeL()
+ {
+ TryChangeFocusToL( EConverterTypePopup );
+ iTypePopupCtrl->ActivateSelectionListL();
+ }
+
+void CCnvMainForm::CmdSetUnitL()
+ {
+ switch ( IdOfFocusControl() )
+ {
+ case EConverterUnit1Popup:
+ {
+ iUnit1PopupCtrl->ActivateSelectionListL();
+ break;
+ }
+
+ case EConverterUnit2Popup:
+ {
+ iUnit2PopupCtrl->ActivateSelectionListL();
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+void CCnvMainForm::LoadStateL()
+ {
+ RFileReadStream in;
+
+ TFileName filePath;
+ TBuf<1> tempDes;
+ TChar driveChar;
+ User::LeaveIfError(iEikonEnv->FsSession().PrivatePath(filePath));
+ iEikonEnv->FsSession().DriveToChar(KDefaultDrive, driveChar);
+ tempDes.Append(driveChar);
+ filePath.Insert(0,KDelimiter);
+ filePath.Insert(0,tempDes);
+ filePath.Append(KConverterFilename);
+
+ TInt err( in.Open( iEikonEnv->FsSession(), filePath,
+ EFileRead ) );
+
+ if( !err )
+ {
+ TRAP( err, iModel->InternalizeL( in ) );
+ if( !err )
+ {
+ TRAP( err, iTypeCategory.SetCurrentValueIndex( in.ReadInt8L() ) );
+ }
+ in.Close();
+ }
+ }
+
+void CCnvMainForm::SaveState()
+ {
+ RFileWriteStream out;
+
+ TFileName filePath;
+ TBuf<1> tempDes;
+ TChar driveChar;
+ TRAPD(errd, iEikonEnv->FsSession().PrivatePath(filePath));
+ iEikonEnv->FsSession().DriveToChar(KDefaultDrive, driveChar);
+ tempDes.Append(driveChar);
+ if(!errd)
+ {
+
+ filePath.Insert(0,KDelimiter);
+ filePath.Insert(0,tempDes);
+ filePath.Append(KConverterFilename);
+ }
+
+ TInt err( out.Replace( iEikonEnv->FsSession(), filePath,
+ EFileWrite ) );
+
+ if( !err )
+ {
+ TRAP( err, iModel->ExternalizeL( out ) );
+ if( !err )
+ {
+ TRAP( err, out.WriteInt8L( iTypeCategory.CurrentValueIndex() ) );
+ }
+ out.Close();
+ }
+
+ if( err && !iHasNotifiedDiscFull )
+ {
+ TRAP_IGNORE(iErrorUI->ShowGlobalErrorNoteL( err ) );
+ iHasNotifiedDiscFull = ETrue;
+ }
+ }
+
+void CCnvMainForm::SynchronousConversionL( TBool aShowRateInvalideNote )
+ {
+ // Don't report an "invalid value" error. Cancel conversion.
+ // if the field is empty (i.e. the user has used delete/backspace) etc.
+ if( EditorValueCausesHold( iLastUsedEditorId ) )
+ {
+ // if one Editor is blank, set the other to 0.
+ CEikFloatingPointEditor* editor =
+ static_cast< CEikFloatingPointEditor* >( Control( iLastUsedEditorId ) );
+ if( editor->TextLength() == 0 )
+ {
+ if( iLastUsedEditorId == EConverterEditor1)
+ {
+ SetFloatEditorValueL( EConverterEditor2, 0.0 );
+ }
+ if( iLastUsedEditorId == EConverterEditor2)
+ {
+ SetFloatEditorValueL( EConverterEditor1, 0.0 );
+ }
+ }
+ return;
+ }
+
+ if ( !IsVaildNumberEntered( iLastUsedEditorId ) )
+ {
+ ShowInvalidValueNoteL( iLastUsedEditorId );
+ }
+
+
+ // PrepareForFocusLossL leaves if the component is not able to
+ // parse the content. We trap it so that IsEditorValueValidL()
+ // can check and report the situation correctly.
+ TRAP_IGNORE( Control( iLastUsedEditorId )->PrepareForFocusLossL() );
+ TInt CurrentControlId( IdOfFocusControl() );
+ if( CurrentControlId == EConverterUnit1Popup )
+ {
+ IsEditorValueValidL( EConverterEditor1 );
+ }
+ else if (CurrentControlId == EConverterUnit2Popup)
+ {
+ IsEditorValueValidL( EConverterEditor2 );
+ }
+ else if (CurrentControlId == EConverterEditor2 )
+ {
+ if ( !IsVaildNumberEntered( EConverterEditor2 ) )
+ {
+ iLastUsedEditorId = CurrentControlId;
+ ShowInvalidValueNoteL( EConverterEditor2 );
+ }
+ }
+ else if (CurrentControlId == EConverterEditor1 )
+ {
+ if ( !IsVaildNumberEntered( EConverterEditor1 ) )
+ {
+ iLastUsedEditorId = CurrentControlId;
+ ShowInvalidValueNoteL( EConverterEditor1 );
+ }
+ }
+ TReal result( 0.0 );
+
+ // send an argument to notify the AreRatesValidL() display a note dialog or not
+ if (IsEditorValueValidL(iLastUsedEditorId))
+ {
+ if (AreRatesValidL(aShowRateInvalideNote))
+ {
+ TReal amount(FloatingPointEditorValue(iLastUsedEditorId));
+ TUint unit1(iUnit1Category.CurrentValueIndex());
+ TUint unit2(iUnit2Category.CurrentValueIndex());
+
+ // RAPD( ignored, Control( iLastUsedEditorId )->PrepareForFocusLossL() );
+
+
+ // do not reset the touch UI to standby state
+ // CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
+
+
+ // Do the calculation and change the value for the related edit field
+ ValueCalculationL(unit1, unit2, amount);
+
+ CEikFloatingPointEditor* editor =
+ static_cast<CEikFloatingPointEditor*> (Control(
+ iLastUsedEditorId));
+ TBuf<KEditorTextMaxLength> editorText;
+ editor->GetText(editorText);
+
+ // Use local value for different area
+ TBuf<1> localeZero;
+ localeZero.AppendNum(0);
+ AknTextUtils::LanguageSpecificNumberConversion(localeZero);
+ if (editorText.Length() > 1 && editorText[0] == localeZero[0])
+ {
+ TCursorSelection sel = editor->Selection();
+ TInt removedZeroes = 0;
+ // remove all leading zeroes
+ while (editorText.Length() > 0 && editorText[0]
+ == localeZero[0])
+ {
+ editorText.Delete(0, 1);
+ ++removedZeroes;
+ }
+ // if too many zeroes removed, insert one.
+ TLocale locale;
+ if (editorText.Length() == 0 || TChar(editorText[0])
+ == locale.DecimalSeparator())
+ {
+ editorText.Insert(0, localeZero);
+ --removedZeroes;
+ }
+ editor->SetTextL(&editorText);
+
+ // adjust the selection accroding to removed zeroes
+ TInt anchor =
+ (sel.iAnchorPos - removedZeroes > 0) ? sel.iAnchorPos
+ - removedZeroes : 0;
+ TInt cursor =
+ (sel.iCursorPos - removedZeroes > 0) ? sel.iCursorPos
+ - removedZeroes : 0;
+ editor->SetSelectionL(cursor, anchor);
+
+ if ( !IsVaildNumberEntered( iLastUsedEditorId ) )
+ {
+ ShowInvalidValueNoteL( iLastUsedEditorId );
+ }
+ // notify the touch window
+ editor->SetCursorPosL(cursor, ETrue);
+ editor->DrawNow();
+ }
+ }
+ }
+ }
+
+void CCnvMainForm::AsynchronousConversion()
+ {
+ CancelConversion();
+ TCallBack cb( TimerCallback, this );
+ iConversionTimer->Start( 750000, 0, cb );
+ }
+
+void CCnvMainForm::CancelConversion()
+ {
+ iConversionTimer->Cancel();
+ }
+
+TInt CCnvMainForm::TimerCallback( TAny* aMainForm )
+ {
+
+ CCnvMainForm* form = reinterpret_cast< CCnvMainForm* >( aMainForm );
+
+ TRAP_IGNORE(form->SynchronousConversionL() );
+
+ form->CancelConversion();
+
+ return KErrNone;
+ }
+
+
+
+// ----------------------------------------------------
+// CCnvMainForm::OfferKeyEventL
+// Keyevent process.
+// ----------------------------------------------------
+//
+TKeyResponse CCnvMainForm::OfferKeyEventL(const TKeyEvent& aKeyEvent,
+ TEventCode aType)
+ {
+
+ if ( !IsFocused() )
+ {
+ if (aKeyEvent.iCode == EKeyEscape)
+ {
+ return CAknForm::OfferKeyEventL( aKeyEvent, aType );
+ }
+ return EKeyWasNotConsumed;
+ }
+
+ TInt controlId( IdOfFocusControl() );
+
+ TBool hashKeyPressed = EFalse;
+
+ // Use decimalChar instead of 46
+ TLocale locale;
+ TChar decimalChar = locale.DecimalSeparator();
+ if ( aKeyEvent.iScanCode == EStdKeyHash || decimalChar == TChar( aKeyEvent.iCode ) )
+ {
+ hashKeyPressed = ETrue;
+ }
+
+ if( hashKeyPressed )
+ {
+ // If inputting through VKB or HWR, the event can be done only when aType is equal to EEventKey.
+ // Besides, only when inputting the dot in VKB or HWR, aKeyEvent.iScanCode is equal to decimalChar.
+ TBool VKBdotKeyPressed = EFalse;
+ if ( ( aKeyEvent.iScanCode == decimalChar ) )
+ {
+ VKBdotKeyPressed = ETrue;
+ }
+ if ( ( aType == EEventKey) && ( !VKBdotKeyPressed ) )
+ {
+ return EKeyWasConsumed;
+ }
+ else if( aType == EEventKeyUp)
+ {
+ TKeyEvent keyevent( aKeyEvent );
+ aType = EEventKey;
+ keyevent.iCode = decimalChar;
+ keyevent.iModifiers = 0;
+ keyevent.iScanCode = 0;
+ keyevent.iRepeats = 0;
+ return static_cast< CEikFloatingPointEditor* >( Control( controlId ) )
+ ->OfferKeyEventL(keyevent,aType);
+ }
+ else
+ {//
+ }
+ }
+
+ //Not a key event this case handles the menu and exit keys
+ //when an invalid value is entered in the amount field
+ if(aType == EEventKeyDown)
+ {
+ if( ( EConverterEditor1 == controlId )||
+ ( EConverterEditor2 == controlId ) )
+ {
+
+ if( (aKeyEvent.iScanCode == EStdKeyDevice0) ||//menu Key
+ (aKeyEvent.iScanCode == EStdKeyDevice1) )//Exit key
+ {
+ if( EditorValueCausesHold( controlId ) ||
+ !IsVaildNumberEntered( controlId ) )
+ {
+ SetFloatEditorValueL( controlId, 0.0);
+ }
+ //return EKeyWasNotConsumed;
+ }
+ }
+ }
+
+ if ( aType != EEventKey )
+ {
+ // Return EKeyWasNotConsumed if OfferKeyEventL() does not handle any event.
+ return EKeyWasNotConsumed;
+ }
+
+ if( ( EConverterEditor1 == controlId )||
+ ( EConverterEditor2 == controlId ) )
+ {
+ //Just to see that -9E-99 doesnt appear when an invalid number is editor is
+ //entered in the editor
+
+ if(aKeyEvent.iScanCode == EStdKeyUpArrow ||
+ aKeyEvent.iScanCode == EStdKeyDownArrow )
+ {
+ CancelConversion();
+ if( EditorValueCausesHold( controlId ) )
+ {
+ SetFloatEditorValueL( controlId, 0.0);
+ }
+ if( !IsVaildNumberEntered( controlId ) )
+ {
+ ShowInvalidValueNoteL( controlId );
+ }
+ }
+
+ iLastUsedEditorId = controlId;
+
+ //For arrow keys asynchronous conversion not required
+ // if (iActiveEditorChanged)
+ // {
+ /*if( ( aKeyEvent.iScanCode != EStdKeyRightArrow )&&
+ ( aKeyEvent.iScanCode != EStdKeyLeftArrow )&&
+ ( aKeyEvent.iScanCode != EStdKeyUpArrow )&&
+ ( aKeyEvent.iScanCode != EStdKeyDownArrow )&&
+ ( isEditKey == EFalse ) )
+ {
+ AsynchronousConversion();
+ }*/
+ //}
+
+ //iActiveEditorChanged = ETrue;
+
+ }
+ return CAknForm::OfferKeyEventL(aKeyEvent, aType);
+
+ }
+
+
+// ----------------------------------------------------
+// CCnvMainForm::IsVaildNumberEntered
+// Checks if a valid number is entered in the editor field and returns
+// ETrue if a vaild number is entered and
+// EFalse if an invalid number is entered
+// ----------------------------------------------------
+//
+
+TBool CCnvMainForm::IsVaildNumberEntered( TInt aEditorId )
+ {
+ CEikFloatingPointEditor* editor =
+ static_cast< CEikFloatingPointEditor* >( Control( aEditorId ) );
+
+ if ( editor->TextLength() == 0 )
+ {
+ return EFalse;
+ }
+
+ TReal real;
+ CAknNumericEdwin::TValidationStatus validationStatus = editor->GetValueAsReal( real );
+
+ // The enter number is not valid if GetValueAsReal function's return value is not EValueValid
+ if ( validationStatus != CAknNumericEdwin::EValueValid /*&& validationStatus != CAknNumericEdwin::EValueTooLarge*/ )
+ {
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+
+
+// ----------------------------------------------------
+// CCnvMainForm::HandleEdwinEventL
+// Checks the Navigation events on the editor
+// ----------------------------------------------------
+//
+
+void CCnvMainForm::HandleEdwinEventL(CEikEdwin* /*aEdwin*/,TEdwinEvent aEventType)
+ {
+ if(EEventNavigation == aEventType)
+ {
+ isEdwinNavigated = ETrue;
+ }
+ if( aEventType == EEventTextUpdate )
+ {
+ isEdwinUpdateText = ETrue;
+ }
+
+ }
+
+// ----------------------------------------------------
+// CCnvMainForm::IsDigit
+// Converts the digit from any digit mode (devangiri or arabic)
+// to western digit and checks whether it is a valid digit or not.
+// ----------------------------------------------------
+//
+TBool CCnvMainForm::IsDigit(TUint aChar)
+ {
+ TBuf<1> digit;
+ digit.Append(aChar);
+
+ AknTextUtils::ConvertDigitsTo(digit , EDigitTypeWestern);
+
+ TChar ch = digit[0];
+ return ch.IsDigit();
+ }
+
+// ----------------------------------------------------
+// CCnvMainForm::PrepareForFocusTransitionL
+// The Uikon framework calls this function immediately before focus move.
+// ----------------------------------------------------
+//
+void CCnvMainForm::PrepareForFocusTransitionL()
+ {
+ TInt controlId( IdOfFocusControl() );
+ if ( ( EConverterEditor1 == controlId ) || ( EConverterEditor2 == controlId ) )
+ {
+
+ // record the last use editor id
+ iLastUsedEditorId = controlId;
+ CancelConversion();
+ if ( EditorValueCausesHold( controlId ) )
+ {
+ SetFloatEditorValueL( controlId, 0.0 );
+ }
+
+ // Delete the radix point when there is no number behind it.
+ else if ( IsVaildNumberEntered( controlId ) )
+ {
+ CEikFloatingPointEditor* editor =
+ static_cast<CEikFloatingPointEditor*> ( Control( controlId ) );
+ TBuf<KEditorTextMaxLength> editorText;
+ editor->GetText( editorText );
+ TLocale locale;
+ TInt editorLength = editorText.Length();
+
+ // Check if the last character is radix point.
+ if ( editorText[ editorLength - 1 ] == locale.DecimalSeparator() )
+ {
+ editorText.Delete( editorLength - 1, 1 );
+ editor->SetTextL( &editorText );
+ }
+ }
+ }
+ }
+
+// ----------------------------------------------------
+// CCnvMainForm::ValueCalculation
+// Do the calculation and change the value for the related edit field
+// ----------------------------------------------------
+//
+void CCnvMainForm::ValueCalculationL( TUint aUnit1Popup, TUint aUnit2Popup, TReal aMount )
+ {
+ TReal result( 0.0 );
+ // Use "LastUnit1" and "LastUnit2" to insure that the second amount don't change if the last used editor
+ // is the second and the category's units do not change.
+ static TInt LastUnit1 = -1;
+ static TInt LastUnit2 = -1;
+
+ // According to the UI Spec:
+ // 1. If the first conversion unit field is changed, a new conversion is calculated to the
+ // second amount field of units, or vice versa.
+ // 2. If the first edit field is changed, a new conversion is calculated to the second
+ // edit field, or vice versa.
+ if ( iLastUsedEditorId == EConverterEditor1 )
+ {
+ //the first unit is changed
+ if ( ( ( IdOfFocusControl() != EConverterEditor1 ) && ( LastUnit1 != aUnit1Popup ) )
+ || ( IdOfFocusControl() == EConverterTypePopup ) )
+ {
+ aMount = FloatingPointEditorValue( EConverterEditor1 );
+ result = iUnit1Category.Convert( aUnit1Popup, aUnit2Popup, aMount );
+ SetFloatEditorValueL( EConverterEditor2, result );
+ }
+ //the second unit is changed
+ else if ( ( IdOfFocusControl() != EConverterEditor1 ) && ( LastUnit2 != aUnit2Popup ) )
+ {
+ aMount = FloatingPointEditorValue( EConverterEditor2 );
+ result = iUnit1Category.Convert( aUnit2Popup, aUnit1Popup, aMount );
+ SetFloatEditorValueL( EConverterEditor1, result );
+ }
+ //the first amount field is changed
+ else
+ {
+ result = iUnit1Category.Convert( aUnit1Popup, aUnit2Popup, aMount );
+ SetFloatEditorValueL( EConverterEditor2, result );
+ }
+ }
+ else
+ {
+ //the first unit is changed
+ if ( ( ( IdOfFocusControl() != EConverterEditor2 ) && ( LastUnit1 != aUnit1Popup ) )
+ || ( IdOfFocusControl() == EConverterTypePopup ))
+ {
+ aMount = FloatingPointEditorValue( EConverterEditor1 );
+ result = iUnit1Category.Convert( aUnit1Popup, aUnit2Popup, aMount );
+ SetFloatEditorValueL( EConverterEditor2, result );
+ }
+ //the second unit is changed
+ else if ( ( IdOfFocusControl() != EConverterEditor2 ) && ( LastUnit2 != aUnit2Popup ) )
+ {
+ aMount = FloatingPointEditorValue( EConverterEditor2 );
+ result = iUnit1Category.Convert( aUnit2Popup, aUnit1Popup, aMount );
+ SetFloatEditorValueL( EConverterEditor1, result );
+ }
+ //the second amount field is changed
+ else
+ {
+ result = iUnit1Category.Convert( aUnit2Popup, aUnit1Popup, aMount );
+ SetFloatEditorValueL( EConverterEditor1, result );
+ }
+ }
+
+ // record units of the category at this time.
+ LastUnit1 = aUnit1Popup;
+ LastUnit2 = aUnit2Popup;
+ }
+//End of file