00001 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). 00002 // All rights reserved. 00003 // This component and the accompanying materials are made available 00004 // under the terms of "Eclipse Public License v1.0" 00005 // which accompanies this distribution, and is available 00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". 00007 // 00008 // Initial Contributors: 00009 // Nokia Corporation - initial contribution. 00010 // 00011 // Contributors: 00012 // 00013 // Description: 00014 // Example wraps a console in an active object. 00015 // Calculates Fibonacci number as chosen by the user. Note that, in this 00016 // example, the calculation is done as part of the console active object's 00017 // RunL() and can take a long time to complete. It also means that nothing 00018 // else can happen (including responding to keyboard events) until the 00019 // calculation is complete. 00020 // 00021 00022 00023 00024 #include <e32base.h> 00025 #include <e32cons.h> 00026 #include <e32std.h> 00027 00028 00029 LOCAL_D CConsoleBase* console; 00030 00031 _LIT(KTxtMainInstructions,"\n\nPress 'F' to start\n 'ESC' to exit.\n"); 00032 00034 // 00035 // -----> CActiveConsole (definition) 00036 // 00037 // An abstract class which provides the facility to issue key requests. 00038 // 00040 00041 class CActiveConsole : public CActive 00042 { 00043 public: 00044 // Construction 00045 CActiveConsole(CConsoleBase* aConsole); 00046 void ConstructL(); 00047 00048 // Destruction 00049 ~CActiveConsole(); 00050 00051 // Issue request 00052 void RequestCharacter(); 00053 00054 // Cancel request. 00055 // Defined as pure virtual by CActive; 00056 // implementation provided by this class. 00057 void DoCancel(); 00058 00059 // Service completed request. 00060 // Defined as pure virtual by CActive; 00061 // implementation provided by this class, 00062 void RunL(); 00063 00064 // Called from RunL() - an implementation must be provided 00065 // by derived classes to handle the completed request 00066 virtual void ProcessKeyPress(TChar aChar) = 0; 00067 00068 protected: 00069 // Data members defined by this class 00070 CConsoleBase* iConsole; // A console for reading from 00071 }; 00072 00073 00075 // 00076 // -----> CExampleScheduler (definition) 00077 // 00079 00080 class CExampleScheduler : public CActiveScheduler 00081 { 00082 public: 00083 void Error (TInt aError) const; 00084 void WaitForAnyRequest(); 00085 void SetActiveObject(CActiveConsole* aActiveConsole); 00086 private: 00087 // data members defined for this class 00088 CActiveConsole* iActiveConsole; 00089 }; 00090 00091 00093 // 00094 // -----> TFibonacciEngine (definition) 00095 // 00096 // This class provides the fibonacci calculation engine 00097 // 00099 00100 class TFibonacciEngine 00101 { 00102 public: 00103 void Calculate (TInt aTerms) ; 00104 00105 TInt iResult ; 00106 } ; 00107 00108 00110 // 00111 // -----> CFibonacciApplication (definition) 00112 // 00113 // This class encapsulates the fibonacci calculation engine 00114 // 00116 00117 class CFibonacciApplication : public CActiveConsole 00118 { 00119 public: 00120 CFibonacciApplication(CConsoleBase* aConsole) ; 00121 void ConstructL(); 00122 00123 // Static construction 00124 static CFibonacciApplication* NewLC(CConsoleBase* aConsole) ; 00125 00126 // service request 00127 void ProcessKeyPress(TChar aChar) ; 00128 00129 private: 00130 CConsoleBase* iConsole ; 00131 TFibonacciEngine iFibonacciEngine ; 00132 }; 00133 00134 00136 // 00137 // -----> CActiveConsole (implementation) 00138 // 00140 00141 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) 00142 : CActive(CActive::EPriorityUserInput) 00143 // Construct high-priority active object 00144 { 00145 iConsole = aConsole; 00146 __DECLARE_NAME(_S("CActiveConsole")); 00147 00148 } 00149 00150 void CActiveConsole::ConstructL() 00151 { 00152 // Add to active scheduler 00153 CActiveScheduler::Add(this); 00154 } 00155 00156 CActiveConsole::~CActiveConsole() 00157 { 00158 // Make sure we're cancelled 00159 Cancel(); 00160 } 00161 00162 void CActiveConsole::DoCancel() 00163 { 00164 iConsole->ReadCancel(); 00165 } 00166 00167 void CActiveConsole::RunL() 00168 { 00169 // Handle completed request 00170 ProcessKeyPress(TChar(iConsole->KeyCode())); 00171 } 00172 00173 void CActiveConsole::RequestCharacter() 00174 { 00175 // A request is issued to the CConsoleBase to accept a 00176 // character from the keyboard. 00177 iConsole->Read(iStatus); 00178 SetActive(); 00179 } 00180 00181 00183 // 00184 // -----> CExampleScheduler (implementation) 00185 // 00187 00188 void CExampleScheduler::Error(TInt aError) const 00189 { 00190 _LIT(KTxtSchedulerError,"CExampleScheduler - error"); 00191 User::Panic(KTxtSchedulerError,aError); 00192 } 00193 00194 void CExampleScheduler::WaitForAnyRequest() 00195 { 00196 if (!(iActiveConsole->IsActive())) 00197 iActiveConsole->RequestCharacter(); 00198 CActiveScheduler::WaitForAnyRequest(); 00199 } 00200 00201 void CExampleScheduler::SetActiveObject(CActiveConsole* aActiveConsole) 00202 { 00203 iActiveConsole = aActiveConsole; 00204 } 00205 00206 00208 // CFibonacciApplication support routine 00209 // uses up arrow & down arrow to change number, Enter to select 00211 00212 TInt GetValueFromKeyboard (TInt aInitial, TInt aStep, TInt lowerLimit, TInt upperLimit, const TDesC& aPrompt, CConsoleBase* aConsole) 00213 { 00214 TChar input ; 00215 TInt value = aInitial ; 00216 00217 aConsole->Printf(aPrompt) ; 00218 do 00219 { 00220 aConsole->SetPos(0); 00221 _LIT(KFormat1,"%d "); 00222 aConsole->Printf(KFormat1, value); 00223 input = aConsole->Getch() ; 00224 if (input == EKeyUpArrow && value < upperLimit) value = value + aStep ; 00225 if (input == EKeyDownArrow && value > lowerLimit) value = value - aStep ; 00226 if (input == 'c') value = -1; 00227 } 00228 while (input != EKeyEnter && input != 'c') ; 00229 00230 return value ; 00231 } 00232 00233 00235 // 00236 // -----> CFibonacciApplication (implementation) 00237 // 00239 00240 CFibonacciApplication::CFibonacciApplication(CConsoleBase* aConsole ) 00241 : CActiveConsole(aConsole) 00242 // construct zero-priority active object 00243 { 00244 iConsole = aConsole ; 00245 __DECLARE_NAME(_S("CFibonacciApplication")); 00246 } 00247 00248 00249 CFibonacciApplication* CFibonacciApplication::NewLC(CConsoleBase* aConsole ) 00250 { 00251 CFibonacciApplication* self=new (ELeave) CFibonacciApplication(aConsole); 00252 CleanupStack::PushL(self); 00253 self->ConstructL(); 00254 return self; 00255 } 00256 00257 00258 void CFibonacciApplication::ConstructL() 00259 { 00260 // Add to active scheduler 00261 CActiveScheduler::Add(this); 00262 // Make this the active object 00263 ((CExampleScheduler*)(CActiveScheduler::Current()))->SetActiveObject(this); 00264 } 00265 00266 00267 void CFibonacciApplication::ProcessKeyPress(TChar aChar) 00268 { 00269 // if key is ESC 00270 // cancel any outstanding request 00271 // stop the scheduler 00272 if (aChar == EKeyEscape) 00273 { 00274 CActiveScheduler::Stop(); 00275 return; 00276 } 00277 00278 // If key is "f" or "F" 00279 // cancel any outstanding request 00280 // issue a fibonacci request. 00281 if (aChar == 'f' || aChar == 'F') 00282 { 00283 _LIT(KTxtStartingFibonacci,"\nStarting Fibonacci.... \n"); 00284 _LIT(KTxtReturnTermNumber,"\nENTER selects number, and starts calculation\nUP arrow increases num\nDOWN arrow decreases num\nC cancels\n\n"); 00285 _LIT(KTxtCalculating,"\nCalculating...\n"); 00286 _LIT(KFormat2,"\nResult : %u \n"); 00287 _LIT(KTxtCancelled,"Cancelled"); 00288 00289 iConsole->Printf(KTxtStartingFibonacci); 00290 00291 TInt iterations = GetValueFromKeyboard(5,1,2,46, KTxtReturnTermNumber, iConsole) ; 00292 if (iterations == -1) // convenient if awkward but allows us to indicate a request to cancel. 00293 { 00294 iConsole->Printf(KTxtCancelled); 00295 iConsole->Printf(KTxtMainInstructions); 00296 return; 00297 } 00298 00299 iConsole->Printf(KTxtCalculating); 00300 iFibonacciEngine.Calculate(iterations); 00301 00302 iConsole->Printf(KFormat2, iFibonacciEngine.iResult) ; 00303 iConsole->Printf(KTxtMainInstructions); 00304 return; 00305 } 00306 00307 // any other key ignore 00308 _LIT(KTxtNotRecognised,"\nUnwanted key pressed"); 00309 iConsole->Printf(KTxtNotRecognised); 00310 iConsole->Printf(KTxtMainInstructions); 00311 } 00312 00314 // 00315 // -----> TFibonacciEngine (implementation) 00316 // 00318 00319 void TFibonacciEngine::Calculate (TInt aTerms) 00320 { 00321 TInt iterations = aTerms ; 00322 00323 TInt currentTotal = 1 ; 00324 TInt previousTotal = 0 ; 00325 _LIT(KTxtTooManyIterations,"Too many iterations"); 00326 __ASSERT_ALWAYS(iterations<47,User::Panic(KTxtTooManyIterations,iterations)); 00327 00328 // if limit not yet reached 00329 while (iterations-- > 0) 00330 { 00331 // calculate next number in series 00332 TInt newTotal = currentTotal + previousTotal ; 00333 00334 // update variables 00335 previousTotal = currentTotal ; 00336 currentTotal = newTotal ; 00337 00338 // introduce a delay 00339 User::After(1000000) ; 00340 } 00341 00342 iResult = currentTotal ; 00343 00344 } 00345 00346 00348 // This section deals with initialisation and ensuring we have a console active 00350 00351 void doExampleL () ; 00352 00353 void SetupConsoleL(); 00354 00355 GLDEF_C TInt E32Main() // main function called by E32 00356 { 00357 CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack 00358 TRAPD(error,SetupConsoleL()); // more initialization, then do example 00359 _LIT(KTxtFibonacciExampleError,"Fibonacci example error"); 00360 __ASSERT_ALWAYS(!error,User::Panic(KTxtFibonacciExampleError,error)); 00361 delete cleanup; // destroy clean-up stack 00362 return 0; // and return 00363 } 00364 00365 void SetupConsoleL() // initialize and call example code under cleanup stack 00366 { 00367 _LIT(KTxtFibSingActObj,"Single Active Object"); 00368 console=Console::NewL(KTxtFibSingActObj, TSize(KConsFullScreen,KConsFullScreen)); 00369 CleanupStack::PushL(console); 00370 00371 console->Printf(KTxtMainInstructions) ; 00372 TRAPD(error, doExampleL()); // perform example function 00373 if (error) 00374 { 00375 _LIT(KFormat3,"failed: leave code=%d"); 00376 console->Printf(KFormat3, error); 00377 } 00378 _LIT(KTxtPressAnyKey,"[Press any key to exit]"); 00379 console->Printf(KTxtPressAnyKey); 00380 console->Getch(); // get and ignore character 00381 CleanupStack::PopAndDestroy(); // close console 00382 } 00383 00384 00386 // 00387 // Do the example 00388 // 00390 void doExampleL() 00391 { 00392 // Construct and install the active scheduler 00393 CExampleScheduler* exampleScheduler = new (ELeave) CExampleScheduler; 00394 00395 // Push onto the cleanup stack 00396 CleanupStack::PushL(exampleScheduler); 00397 00398 // Install as the active scheduler 00399 CActiveScheduler::Install(exampleScheduler); 00400 00401 // Create CFibonacciApplication active object. 00402 CFibonacciApplication* fibonacci = CFibonacciApplication::NewLC(console); 00403 00404 // issue initial request 00405 fibonacci->RequestCharacter() ; 00406 00407 // Main part of the program: 00408 // wait loop that cycles until ActiveScheduler::Stop called 00409 CActiveScheduler::Start(); 00410 00411 // Remove from the cleanup stack and destroy: 00412 // 1. the CFibonacciApplication active object. 00413 // 2. exampleScheduler 00414 CleanupStack::PopAndDestroy(); 00415 CleanupStack::PopAndDestroy(); 00416 } 00417
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.