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 // Asynchronous keyboard processing with messenger program. 00015 // A single CKeyMessengerProcessor active object (derived from 00016 // class CActiveConsole) which accepts input from keyboard, but does not 00017 // print it. 00018 // This object contains a CMessageTimer object which it activates if the 00019 // user inputs the character "m" and cancelled if the user inputs "c" . 00020 // All keyboard requests are issued from the active scheduler. 00021 // 00022 00023 00024 #include "CommonFramework.h" 00025 00026 // 00027 // Common literal text 00028 // 00029 _LIT(KTxtNewLine,"\n"); 00030 00031 00032 // panics 00033 enum 00034 { 00035 EPanicAlreadyActive=1000, 00036 }; 00037 00038 00040 // 00041 // -----> CTimedMessenger (definition) 00042 // 00044 class CTimedMessenger : public CTimer 00045 { 00046 public: 00047 // Construction 00048 CTimedMessenger(); 00049 // Destruction 00050 ~CTimedMessenger(); 00051 00052 public: 00053 // Static construction 00054 static CTimedMessenger* NewLC(const TDesC& aGreeting, 00055 TInt aTicksRequested, 00056 TInt aTicksInterval 00057 ); 00058 static CTimedMessenger* NewL(const TDesC& aGreeting, 00059 TInt aTicksRequested, 00060 TInt aTicksInterval 00061 ); 00062 00063 public: 00064 // Second phase construction 00065 void ConstructL(const TDesC& aGreeting, 00066 TInt aTicksRequested, 00067 TInt aTicksInterval 00068 ); 00069 00070 // issue request 00071 void IssueRequest(); 00072 00073 // Cancel request 00074 // Defined as pure virtual by CActive; 00075 // implementation provided by this class. 00076 void DoCancel(); 00077 00078 // service completed request. 00079 // Defined as pure virtual by CActive; 00080 // implementation provided by this class. 00081 void RunL(); 00082 00083 public: 00084 // data members defined by this class 00085 TBufC<20> iGreeting; // Text of the greeting. 00086 TInt iTicksRequested; // Total number of greetings CTimedMessenger 00087 // will emit. 00088 TInt iTicksInterval; // Number of seconds between each greeting. 00089 TInt iTicksDone; // Number of greetings issued so far. 00090 }; 00091 00092 00094 // 00095 // -----> CExampleScheduler (definition) 00096 // 00098 class CActiveConsole; 00099 class CExampleScheduler : public CActiveScheduler 00100 { 00101 public: 00102 void Error (TInt aError) const; 00103 void WaitForAnyRequest(); 00104 void SetActiveObject(CActiveConsole* aActiveConsole); 00105 private: 00106 // data members defined for this class 00107 CActiveConsole* iActiveConsole; 00108 }; 00109 00110 00112 // 00113 // -----> CActiveConsole (definition) 00114 // 00115 // An abstract class which provides the facility to issue key requests. 00116 // 00118 class CActiveConsole : public CActive 00119 { 00120 public: 00121 // Construction 00122 CActiveConsole(CConsoleBase* aConsole); 00123 void ConstructL(); 00124 00125 // Destruction 00126 ~CActiveConsole(); 00127 00128 // Issue request 00129 void RequestCharacter(); 00130 00131 // Cancel request. 00132 // Defined as pure virtual by CActive; 00133 // implementation provided by this class. 00134 void DoCancel(); 00135 00136 // Service completed request. 00137 // Defined as pure virtual by CActive; 00138 // implementation provided by this class, 00139 void RunL(); 00140 00141 // Called from RunL() - an implementation must be provided 00142 // by derived classes to handle the completed request 00143 virtual void ProcessKeyPress(TChar aChar) = 0; 00144 00145 protected: 00146 // Data members defined by this class 00147 CConsoleBase* iConsole; // A console for reading from 00148 }; 00149 00150 00152 // 00153 // -----> CWriteKeyProcessor (definition) 00154 // 00155 // This class is derived from CActiveConsole. 00156 // Request handling: accepts input from the keyboard and outputs it 00157 // to the console. 00158 // 00160 class CWriteKeyProcessor : public CActiveConsole 00161 { 00162 public: 00163 // Construction 00164 CWriteKeyProcessor(CConsoleBase* aConsole); 00165 00166 public: 00167 // Static constuction 00168 static CWriteKeyProcessor *NewLC (CConsoleBase* aConsole); 00169 static CWriteKeyProcessor *NewL(CConsoleBase* aConsole); 00170 00171 // Service request 00172 void ProcessKeyPress(TChar aChar); 00173 }; 00174 00175 00177 // 00178 // -----> CTimedMessenger (implementation) 00179 // 00181 CTimedMessenger::CTimedMessenger() 00182 : CTimer(CActive::EPriorityStandard) 00183 // Construct standard-priority active object 00184 {}; 00185 00186 CTimedMessenger* CTimedMessenger::NewLC(const TDesC& aGreeting, 00187 TInt aTicksRequested, 00188 TInt aTicksInterval 00189 ) 00190 { 00191 CTimedMessenger* self=new (ELeave) CTimedMessenger; 00192 CleanupStack::PushL(self); 00193 self->ConstructL(aGreeting,aTicksRequested,aTicksInterval); 00194 return self; 00195 } 00196 00197 CTimedMessenger* CTimedMessenger::NewL(const TDesC& aGreeting, 00198 TInt aTicksRequested, 00199 TInt aTicksInterval 00200 ) 00201 { 00202 CTimedMessenger* self = NewLC(aGreeting,aTicksRequested,aTicksInterval); 00203 CleanupStack::Pop(); 00204 return self; 00205 } 00206 00207 void CTimedMessenger::ConstructL(const TDesC& aGreeting, 00208 TInt aTicksRequested, 00209 TInt aTicksInterval 00210 ) 00211 { 00212 // Base class second-phase construction. 00213 CTimer::ConstructL(); 00214 // Set members from arguments 00215 iGreeting = aGreeting; // Set greeting text. 00216 iTicksRequested = aTicksRequested; // Ticks requested 00217 iTicksInterval = aTicksInterval; // Interval between ticks 00218 // Add active object to active scheduler 00219 CActiveScheduler::Add(this); 00220 } 00221 00222 00223 CTimedMessenger::~CTimedMessenger() 00224 { 00225 // Make sure we're cancelled 00226 Cancel(); 00227 } 00228 00229 void CTimedMessenger::DoCancel() 00230 { 00231 // Base class 00232 CTimer::DoCancel(); 00233 // Reset this variable - needed if the object is re-activated later 00234 iTicksDone = 0; 00235 // Tell user 00236 _LIT(KTxtOutMessReqCancelled,"Outstanding Messenger request cancelled\n"); 00237 console->Printf(KTxtOutMessReqCancelled); 00238 } 00239 00240 void CTimedMessenger::IssueRequest() 00241 { 00242 // There should never be an outstanding request at this point. 00243 _LIT(KTxtIsAlreadyActive,"Is already Active"); 00244 __ASSERT_ALWAYS(!IsActive(),User::Panic(KTxtIsAlreadyActive,EPanicAlreadyActive)); 00245 // Request another wait 00246 CTimer::After( iTicksInterval*1000000); 00247 } 00248 00249 void CTimedMessenger::RunL() 00250 { 00251 // Handle request completion 00252 // One more tick done 00253 iTicksDone++; 00254 // Print greeting 00255 _LIT(KFormat1,"%S \n"); 00256 console->Printf(KFormat1,&iGreeting); 00257 // Issue new request, or stop if we have reached the limit 00258 if (iTicksDone < iTicksRequested) 00259 { 00260 IssueRequest(); 00261 } 00262 else 00263 { 00264 _LIT(KTxtMessengerFinished,"Messenger finished \n"); 00265 console->Printf(KTxtMessengerFinished); 00266 // Reset this variable - needed if the object is re-activated later 00267 iTicksDone=0; 00268 // Can now stop the active scheduler 00269 CActiveScheduler::Stop(); 00270 } 00271 } 00272 00273 00275 // 00276 // -----> CExampleScheduler (implementation) 00277 // 00279 void CExampleScheduler::Error(TInt aError) const 00280 { 00281 _LIT(KTxtSchedulerError,"CExampleScheduler - error"); 00282 User::Panic(KTxtSchedulerError,aError); 00283 } 00284 00285 00286 void CExampleScheduler::WaitForAnyRequest() 00287 { 00288 if (!(iActiveConsole->IsActive())) 00289 iActiveConsole->RequestCharacter(); 00290 CActiveScheduler::WaitForAnyRequest(); 00291 } 00292 00293 void CExampleScheduler::SetActiveObject(CActiveConsole* aActiveConsole) 00294 { 00295 iActiveConsole = aActiveConsole; 00296 } 00297 00298 00300 // 00301 // -----> CActiveConsole (implementation) 00302 // 00304 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) 00305 : CActive(CActive::EPriorityUserInput) 00306 // Construct high-priority active object 00307 { 00308 iConsole = aConsole; 00309 } 00310 00311 void CActiveConsole::ConstructL() 00312 { 00313 // Add to active scheduler 00314 CActiveScheduler::Add(this); 00315 } 00316 00317 CActiveConsole::~CActiveConsole() 00318 { 00319 // Make sure we're cancelled 00320 Cancel(); 00321 } 00322 00323 void CActiveConsole::DoCancel() 00324 { 00325 iConsole->ReadCancel(); 00326 } 00327 00328 void CActiveConsole::RunL() 00329 { 00330 // Handle completed request 00331 ProcessKeyPress(TChar(iConsole->KeyCode())); 00332 } 00333 00334 void CActiveConsole::RequestCharacter() 00335 { 00336 // A request is issued to the CConsoleBase to accept a 00337 // character from the keyboard. 00338 iConsole->Read(iStatus); 00339 SetActive(); 00340 } 00341 00342 00344 // 00345 // -----> CWriteKeyProcessor (implementation) 00346 // 00348 CWriteKeyProcessor::CWriteKeyProcessor(CConsoleBase* aConsole) 00349 : CActiveConsole(aConsole) 00350 // Construct zero-priority active object 00351 {}; 00352 00353 CWriteKeyProcessor* CWriteKeyProcessor::NewLC(CConsoleBase* aConsole) 00354 { 00355 CWriteKeyProcessor* self=new (ELeave) CWriteKeyProcessor(aConsole); 00356 CleanupStack::PushL(self); 00357 self->ConstructL(); 00358 return self; 00359 } 00360 00361 CWriteKeyProcessor* CWriteKeyProcessor::NewL(CConsoleBase* aConsole) 00362 { 00363 CWriteKeyProcessor* self=NewLC(aConsole); 00364 CleanupStack::Pop(); 00365 return self; 00366 } 00367 00368 void CWriteKeyProcessor::ProcessKeyPress(TChar aChar) 00369 { 00370 // "Esc" character prints a new line and stops the scheduler 00371 if (aChar == EKeyEscape) 00372 { 00373 iConsole->Printf(KTxtNewLine); 00374 CActiveScheduler::Stop(); 00375 return; 00376 } 00377 00378 // "Enter" prints a new line character 00379 // An alphabetic or space is printed as a character; 00380 // anything else is printed as an integer. 00381 if (aChar == EKeyEnter) 00382 iConsole->Printf(KTxtNewLine); 00383 else 00384 { 00385 _LIT(KFormat2,"%c"); 00386 _LIT(KFormat3,"%d"); 00387 if (aChar.IsAlphaDigit()|| aChar.IsSpace()) 00388 00389 iConsole->Printf(KFormat2,TUint(aChar)); 00390 else 00391 iConsole->Printf(KFormat3,TUint(aChar)); 00392 } 00393 00394 // Issue another request 00395 RequestCharacter(); 00396 } 00397 00398 00400 // 00401 // -----> CMessageKeyProcessor (definition) 00402 // 00403 // This class is derived from CActiveConsole. 00404 // Request handling: 00405 // if key is "m", a message timer request is issued. 00406 // if key is "c", any outstanding message timer request is cancelled. 00407 // If key is ESC, the wait loop is terminated. 00408 // 00410 class CMessageKeyProcessor : public CActiveConsole 00411 { 00412 public: 00413 // Construction 00414 CMessageKeyProcessor(CConsoleBase* aConsole, CTimedMessenger* iMessenger); 00415 void ConstructL(); 00416 00417 public: 00418 // Static construction 00419 static CMessageKeyProcessor* NewLC(CConsoleBase* aConsole, 00420 CTimedMessenger* iMessenger 00421 ); 00422 static CMessageKeyProcessor* NewL(CConsoleBase* aConsole, 00423 CTimedMessenger* iMessenger 00424 ); 00425 00426 public: 00427 // service request 00428 void ProcessKeyPress(TChar aChar); 00429 00430 private: 00431 // Data members defined by this class 00432 CTimedMessenger* iMessenger; 00433 }; 00434 00436 // 00437 // -----> CMessageKeyProcessor (implementation) 00438 // 00440 CMessageKeyProcessor::CMessageKeyProcessor(CConsoleBase* aConsole, 00441 CTimedMessenger* aMessenger 00442 ) 00443 : CActiveConsole(aConsole) 00444 // construct zero-priority active object 00445 { 00446 iMessenger = aMessenger; 00447 } 00448 00449 CMessageKeyProcessor* CMessageKeyProcessor::NewLC(CConsoleBase* aConsole, 00450 CTimedMessenger* aMessenger 00451 ) 00452 { 00453 CMessageKeyProcessor* self=new (ELeave) CMessageKeyProcessor(aConsole, 00454 aMessenger 00455 ); 00456 CleanupStack::PushL(self); 00457 self->ConstructL(); 00458 return self; 00459 } 00460 00461 CMessageKeyProcessor* CMessageKeyProcessor::NewL(CConsoleBase* aConsole, 00462 CTimedMessenger* aMessenger 00463 ) 00464 { 00465 CMessageKeyProcessor* self = NewLC(aConsole, aMessenger); 00466 CleanupStack::Pop(); 00467 return self; 00468 } 00469 00470 void CMessageKeyProcessor::ConstructL() 00471 { 00472 // Add to active scheduler 00473 CActiveScheduler::Add(this); 00474 // Make this the active object 00475 ((CExampleScheduler*)(CActiveScheduler::Current()))->SetActiveObject(this); 00476 } 00477 00478 void CMessageKeyProcessor::ProcessKeyPress(TChar aChar) 00479 { 00480 // if key is ESC 00481 // cancel any outstanding request 00482 // stop the scheduler 00483 if (aChar == EKeyEscape) 00484 { 00485 iMessenger->Cancel(); 00486 CActiveScheduler::Stop(); 00487 return; 00488 } 00489 00490 // If key is "m" or "M" 00491 // cancel any outstanding request 00492 // reset the tick counter 00493 // issue a message timer request. 00494 if (aChar == 'm' || aChar == 'M') 00495 { 00496 _LIT(KTxtStartingMess,"Starting Messenger.... \n"); 00497 iConsole->Printf(KTxtStartingMess); 00498 iMessenger->Cancel(); 00499 iMessenger ->IssueRequest(); 00500 } 00501 00502 // If key is "c" or "C" 00503 // cancel any outstanding request 00504 if (aChar == 'c' || aChar == 'C') 00505 iMessenger->Cancel(); 00506 } 00507 00508 00510 // 00511 // Do the example 00512 // 00514 LOCAL_C void doExampleL() 00515 { 00516 // Construct and install the active scheduler 00517 CExampleScheduler* exampleScheduler = new (ELeave) CExampleScheduler; 00518 00519 // Push onto the cleanup stack 00520 CleanupStack::PushL(exampleScheduler); 00521 00522 // Install as the active scheduler 00523 CActiveScheduler::Install(exampleScheduler); 00524 00525 // Create a CTimedMessenger active object which will emit 00526 // 3 messages with an interval of 2 seconds between messages. 00527 _LIT(KTxtGoodMorning,"Good Morning!"); 00528 CTimedMessenger* messenger = CTimedMessenger::NewLC(KTxtGoodMorning, 3, 2); 00529 00530 // Create aCMessageKeyProcessor active object. 00531 _LIT(KTxtMain1,"A single CKeyMessengerProcessor active object "); 00532 _LIT(KTxtMain2,"Active scheduler renews request.\n"); 00533 _LIT(KTxtMain3,"Press 'm' to activate messenger; Press 'c' to cancel it.\n"); 00534 _LIT(KTxtMain4,"Press ESC to end.\n\n"); 00535 console->Printf(KTxtMain1); 00536 console->Printf(KTxtMain2); 00537 console->Printf(KTxtMain3); 00538 console->Printf(KTxtMain4); 00539 CMessageKeyProcessor::NewLC(console,messenger); 00540 00541 // Main part of the program is a wait loop 00542 CActiveScheduler::Start(); 00543 00544 // Remove from the cleanup stack and destroy: 00545 // 1. the CTimedMessenger active object 00546 // 2. the CMessageKeyProcessor active object. 00547 // 3. exampleScheduler 00548 CleanupStack::PopAndDestroy(3); 00549 } 00550 00551 00552
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.