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