diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_custom_controls_8cpp-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_custom_controls_8cpp-source.html Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,613 @@ + +
+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 // UI Control Framework example program +00015 // This example demonstrates how to write new control classes. +00016 // The example creates three new control classes: +00017 // 1. CSmiley - a simple control which displays a +00018 // smiley face that can have two moods, +00019 // happy and sad. The user can change +00020 // the smiley's mood by pressing the +00021 // space bar. +00022 // 2. CSmileyContainer - a compound control which contains +00023 // two CSmiley controls, side by side. +00024 // The user can move the keyboard focus +00025 // from one CSmiley to the other using +00026 // the arrow keys, or the pointer. +00027 // 3. CMainWinControl - a compound control which does nothing +00028 // except act as a background window and a +00029 // container for other controls in the +00030 // application. +00031 // When the application starts up, it creates a CMainWinControl to cover +00032 // the entire screen, and a CSmileyContainer inside this main window. +00033 // The application's menu contains just two options. One of them closes +00034 // the application; the other creates a dialog which contains a +00035 // CSmileyContainer. CSmileyContainer therefore illustrates how to write +00036 // a control that can be created both in a dialog and within the +00037 // application's main view. +00038 // +00039 +00040 #include "CustomControls.h" +00041 #include <eikstart.h> +00042 +00043 +00045 // +00046 // -----> CMainWinControl(implementation) +00047 // +00049 CMainWinControl::CMainWinControl() +00050 { +00051 } +00052 +00053 CMainWinControl::~CMainWinControl() +00054 { +00055 delete iContainer; +00056 } +00057 +00058 // CMainWinControl needs a ConstructL(), because it is a compound control +00059 // (and a window-owning control). +00060 void CMainWinControl::ConstructL(const TRect& rect) +00061 { +00062 // Make this a window-owning control. +00063 CreateWindowL(); +00064 SetRect(rect); +00065 +00066 // Create its only component, a CSmileyContainer +00067 iContainer = new(ELeave) CSmileyContainer; +00068 iContainer->SetContainerWindowL(*this); +00069 TRect containerRect=Rect(); +00070 iContainer->ConstructL(containerRect); +00071 // Activate the main window control - this will also activate the +00072 // CSmileyContainer and its components. +00073 ActivateL(); +00074 DrawNow(); +00075 } +00076 +00077 // The following two functions have to be implemented for all compound controls. +00078 TInt CMainWinControl::CountComponentControls() const +00079 { +00080 return 1; +00081 } +00082 +00083 CCoeControl* CMainWinControl::ComponentControl(TInt /*aIndex*/) const +00084 { +00085 return iContainer; +00086 } +00087 +00088 // Draw the main window. +00089 void CMainWinControl::Draw(const TRect& /*aRect*/) const +00090 { +00091 CWindowGc& gc=SystemGc(); +00092 gc.SetBrushColor(KRgbWhite); +00093 gc.Clear(Rect()); +00094 } +00095 +00096 // CSmileyContainer can't be put on the control stack, because it's a component of this +00097 // control. The main window control goes on the stack and passes on any key events it gets +00098 // to the CSmileyContainer. +00099 TKeyResponse CMainWinControl::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType) +00100 { +00101 return (iContainer->OfferKeyEventL(aKeyEvent, aType)); +00102 } +00103 +00105 // +00106 // -----> CSmileyContainer (implementation) +00107 // +00109 CSmileyContainer::CSmileyContainer() +00110 {} +00111 +00112 +00113 CSmileyContainer::~CSmileyContainer() +00114 { +00115 // Delete all the contained controls +00116 delete iSmiley1; +00117 delete iSmiley2; +00118 } +00119 +00120 +00121 // Because CSmileyContainer is a compound control, it needs a +00122 // ConstructL() for when it's created outside a dialog, and a +00123 // ConstructFromResourceL() for when it's created inside a dialog. +00124 void CSmileyContainer::ConstructL(const TRect& aRect) +00125 { +00126 TBool isSmiling=ETrue; +00127 +00128 // Create the two CSmileys. Their size and position is +00129 // set in CSmileyContainer::SizeChangedL(). +00130 iSmiley1 = new(ELeave) CSmiley(isSmiling); +00131 iSmiley1->SetContainerWindowL(*this); +00132 +00133 isSmiling=EFalse; +00134 +00135 iSmiley2 = new(ELeave) CSmiley(isSmiling); +00136 iSmiley2->SetContainerWindowL(*this); +00137 +00138 iSmiley1->SetFocus(ETrue); +00139 +00140 // Set the container as the observer of the two CSmileys. This +00141 // is for handling keyboard focus. When an arrow key is pressed +00142 // or the pointer is clicked on one of the CSmileys, an +00143 // EEventRequestFocus event is sent to the container, and the +00144 // container changes the focus if applicable. +00145 iSmiley1->SetObserver(this); +00146 iSmiley2->SetObserver(this); +00147 +00148 // Set the bounding rectangle of this control (this will result in +00149 // a call to SizeChangedL(). The component controls must be +00150 // created before calling this, because SizeChangedL() sets their +00151 // sizes. +00152 SetRect(aRect); +00153 } +00154 +00155 +00156 // This function is used when the CSmileyContainer is created inside a dialog. +00157 void CSmileyContainer::ConstructFromResourceL(TResourceReader& aReader) +00158 { +00159 // Read the smiley mood from the resource file +00160 TBool isSmiling=(TBool)aReader.ReadInt8(); +00161 // Read the width of the smiley container from the resource file. +00162 TInt width=aReader.ReadInt16(); +00163 // Set the height of the container to be half its width +00164 TSize containerSize (width, width/2); +00165 +00166 iSmiley1 = new(ELeave) CSmiley(isSmiling); +00167 iSmiley1->SetContainerWindowL(*this); +00168 +00169 iSmiley2 = new(ELeave) CSmiley(isSmiling); +00170 iSmiley2->SetContainerWindowL(*this); +00171 +00172 iSmiley1->SetFocus(ETrue); +00173 +00174 iSmiley1->SetObserver(this); +00175 iSmiley2->SetObserver(this); +00176 +00177 SetSize(containerSize); +00178 +00179 ActivateL(); +00180 } +00181 +00182 // The following two functions have to be implemented for all compound controls. +00183 TInt CSmileyContainer::CountComponentControls() const +00184 { +00185 return 2; +00186 } +00187 +00188 CCoeControl* CSmileyContainer::ComponentControl(TInt aIndex) const +00189 { +00190 if (aIndex==0) +00191 return iSmiley1; +00192 else +00193 return iSmiley2; +00194 } +00195 +00196 // This function gets called whenever one of the size-setting functions is called. +00197 // As this is a compound control, this function calculates and sets the size and +00198 // position for its components, based on its own size. +00199 void CSmileyContainer::SizeChanged() +00200 { +00201 TInt containerWidth=Size().iWidth; +00202 TInt containerHeight=Size().iHeight; +00203 // Find half of the greater - width or height +00204 TInt length=containerHeight>containerWidth ? containerWidth/4 : containerHeight/4; +00205 TSize smileySize(length,length); +00206 +00207 // Do some preliminary calculations so that Draw() is as short +00208 // as possible. +00209 TInt xOffset=smileySize.iWidth/4; // x offset from the center +00210 TInt yOffset=(containerHeight - smileySize.iHeight) / 2; +00211 iSmiley1->SetPosition(Position() + +00212 TPoint(containerWidth/2 - smileySize.iWidth - xOffset, yOffset)); +00213 iSmiley2->SetPosition(Position() + +00214 TPoint(containerWidth/2 + xOffset, yOffset)); +00215 // Calling SetSizeL() causes the components' SizeChanged() to be called. +00216 iSmiley1->SetSize(smileySize); +00217 iSmiley2->SetSize(smileySize); +00218 } +00219 +00220 void CSmileyContainer::Draw(const TRect& aRect) const +00221 { +00222 // Just draw a rectangle round the edge of the control. +00223 CWindowGc& gc=SystemGc(); +00224 gc.Clear(aRect); +00225 gc.SetClippingRect(aRect); +00226 gc.DrawRect(Rect()); +00227 } +00228 +00229 // This function is defined by MCoeControlObserver. It gets called whenever +00230 // a control that this control is observing calls ReportEventL(). +00231 // In this example, the CSmileyContainer is the observer for both of the +00232 // CSmileys. CCoeControl::ProcessPointerEventL() calls ReportEvent(), +00233 // sending an event of type EEventRequestFocus, whenever an EButton1Down event +00234 // occurs in the CSmiley that doesn't currently have focus. +00235 void CSmileyContainer::HandleControlEventL(CCoeControl* aControl, +00236 TCoeEvent aEventType) +00237 { +00238 switch (aEventType) +00239 { +00240 case EEventRequestFocus: +00241 { +00242 if (aControl->IsFocused()) +00243 return; +00244 SwapFocus(aControl); +00245 } +00246 break; +00247 default: +00248 break; +00249 } +00250 } +00251 +00252 // This function is called by the framework whenever a component in a dialog is +00253 // about to lose focus. It checks that the data in ithe component is valid. In +00254 // this example, there's a "rule" that both the CSmileys in the container can't +00255 // be miserable! If they are, the function leaves. The framework issues the message +00256 // we give it, and doesn't move focus away from the CSmileyContainer. +00257 void CSmileyContainer::PrepareForFocusLossL() +00258 { +00259 if (!iSmiley1->IsSmiling() && !iSmiley2->IsSmiling()) +00260 { +00261 CEikonEnv::Static()->LeaveWithInfoMsg(R_EXAMPLE_TEXT_VALIDATE); +00262 } +00263 } +00264 +00265 // This function gets called whenever the application calls SetFocus(). +00266 // It redraws the CSmileyContainer, so that they are updated to show +00267 // which one now has focus. +00268 void CSmileyContainer::FocusChanged(TDrawNow aDrawNow) +00269 { +00270 if (IsFocused()) +00271 { +00272 iSmiley1->SetFocus(ETrue, EDrawNow); +00273 } +00274 else +00275 { +00276 if (iSmiley1->IsFocused()) +00277 iSmiley1->SetFocus(EFalse, EDrawNow); +00278 else +00279 iSmiley2->SetFocus(EFalse, EDrawNow); +00280 } +00281 if (aDrawNow) +00282 DrawNow(); +00283 } +00284 +00285 +00286 void CSmileyContainer::SwapFocus(CCoeControl* aControl) +00287 { +00288 if (aControl==iSmiley1) +00289 { +00290 iSmiley2->SetFocus(EFalse, EDrawNow); +00291 iSmiley1->SetFocus(ETrue, EDrawNow); +00292 } +00293 else +00294 { +00295 iSmiley1->SetFocus(EFalse, EDrawNow); +00296 iSmiley2->SetFocus(ETrue, EDrawNow); +00297 } +00298 } +00299 +00300 TKeyResponse CSmileyContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) +00301 { +00302 // Use the arrow keys to move focus between the two CSmileys. +00303 switch (aKeyEvent.iScanCode) +00304 { +00305 case EStdKeySpace: +00306 if (iSmiley1->IsFocused()) +00307 return iSmiley1->OfferKeyEventL(aKeyEvent, aType); +00308 else if (iSmiley2->IsFocused()) +00309 return iSmiley2->OfferKeyEventL(aKeyEvent, aType); +00310 break; +00311 case EStdKeyRightArrow: +00312 if (iSmiley1->IsFocused()) +00313 SwapFocus(iSmiley2); +00314 else +00315 return EKeyWasConsumed; +00316 break; +00317 case EStdKeyLeftArrow: +00318 if (iSmiley2->IsFocused()) +00319 SwapFocus(iSmiley1); +00320 else +00321 return EKeyWasConsumed; +00322 break; +00323 default: +00324 break; +00325 } +00326 // If the CSmileyContainer didn't use the key event, it must return EKeyWasNotConsumed, +00327 // so that the key event is passed to other controls on the stack. +00328 return EKeyWasNotConsumed; +00329 } +00330 +00331 +00332 +00333 +00335 // +00336 // -----> CSmiley (implementation) +00337 // +00339 +00340 // CSmiley doesn't need a ConstructL() because it's a simple control. +00341 +00342 CSmiley::CSmiley(TBool aSmiling) : iSmiling(aSmiling) +00343 { +00344 } +00345 +00346 CSmiley::~CSmiley() +00347 { +00348 } +00349 +00350 TBool CSmiley::IsSmiling() +00351 { +00352 return iSmiling; +00353 } +00354 +00355 void CSmiley::Draw(const TRect& aRect) const +00356 { +00357 CWindowGc& gc=SystemGc(); +00358 if (IsFocused()) +00359 { +00360 gc.SetPenColor(KRgbBlack); +00361 } +00362 else +00363 { +00364 gc.SetPenColor(KRgbWhite); +00365 } +00366 gc.SetBrushColor(KRgbWhite); +00367 gc.Clear(Rect()); +00368 gc.DrawRect(Rect()); +00369 +00370 gc.SetClippingRect(aRect); +00371 +00372 // Draw the smiley face, smiling or looking sad +00373 gc.SetPenColor(KRgbBlack); +00374 // Draw a circle for the face +00375 gc.DrawEllipse(iSmileyRect); +00376 // Draw the eyes +00377 TPoint leftEye(iSmileyWidth/3, iSmileyHeight/3); +00378 TPoint rightEye(iSmileyWidth*2/3, iSmileyHeight/3); +00379 gc.SetPenSize(TSize(5,5)); +00380 gc.Plot(iSmileyRect.iTl+leftEye); +00381 gc.Plot(iSmileyRect.iTl+rightEye); +00382 //Draw the mouth, smiling or looking sad. +00383 gc.SetPenSize(TSize(1,1)); +00384 gc.SetPenColor(KRgbWhite); +00385 if (iSmiling) +00386 gc.DrawArc(iFrownRect, iFrownRect.iTl+TPoint(iSmileyWidth/2,iFrownRect.Height()/2), +00387 iFrownRect.iTl+TPoint(0,iFrownRect.Height()/2)); +00388 else +00389 gc.DrawArc(iSmileRect, iSmileRect.iTl+TPoint(0,iSmileRect.Height()/2), +00390 iSmileRect.iTl+TPoint(iSmileyWidth/2,iSmileRect.Height()/2)); +00391 gc.SetPenColor(KRgbBlack); +00392 if (iSmiling) +00393 gc.DrawArc(iSmileRect, iSmileRect.iTl+TPoint(0,iSmileRect.Height()/2), +00394 iSmileRect.iTl+TPoint(iSmileyWidth/2,iSmileRect.Height()/2)); +00395 else +00396 gc.DrawArc(iFrownRect, iFrownRect.iTl+TPoint(iSmileyWidth/2,iFrownRect.Height()/2), +00397 iFrownRect.iTl+TPoint(0,iFrownRect.Height()/2)); +00398 } +00399 +00400 void CSmiley::SizeChanged() +00401 { +00402 // Calculate sizes of rectangles for drawing face and mouth +00403 iSmileyRect=Rect(); +00404 // Allow room for the focus rectangle round the outside +00405 iSmileyRect.Shrink(3,3); +00406 iSmileyWidth=iSmileyRect.Width(); +00407 iSmileyHeight=iSmileyRect.Height(); +00408 iSmileRect.SetRect(iSmileyRect.iTl+TPoint(iSmileyWidth/4, iSmileyHeight/2), +00409 TSize(iSmileyWidth/2, iSmileyHeight/3)); +00410 iFrownRect.SetRect(iSmileyRect.iTl+TPoint(iSmileyWidth/4, iSmileyHeight*2/3), +00411 TSize(iSmileyWidth/2, iSmileyHeight/3)); +00412 } +00413 +00414 void CSmiley::FocusChanged(TDrawNow aDrawNow) +00415 { +00416 if (aDrawNow) +00417 DrawNow(); +00418 } +00419 +00420 void CSmiley::HandlePointerEventL(const TPointerEvent& aPointerEvent) +00421 { +00422 if (aPointerEvent.iType==TPointerEvent::EButton1Down) +00423 { +00424 iSmiling = !iSmiling; +00425 DrawNow(); +00426 } +00427 } +00428 +00429 TKeyResponse CSmiley::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) +00430 { +00431 // The space bar changes the "mood" of the CSmiley. +00432 if (aType==EEventKey && aKeyEvent.iScanCode==EStdKeySpace) +00433 { +00434 iSmiling = !iSmiling; +00435 DrawNow(); +00436 return EKeyWasConsumed; +00437 } +00438 else +00439 { +00440 return EKeyWasNotConsumed; +00441 } +00442 } +00443 +00445 // +00446 // -----> CSmileyDialog(implementation) +00447 // +00449 TBool CSmileyDialog::RunDlgLD() +00450 { +00451 CEikDialog* dialog = new (ELeave) CSmileyDialog(); +00452 return (dialog->ExecuteLD(R_SMILEY_DIALOG)); +00453 } +00454 +00455 // This function is used by CEikForm::ConstructByTypeL() to create the custom +00456 // control within the dialog. +00457 SEikControlInfo CSmileyDialog::CreateCustomControlL(TInt aControlType) +00458 { +00459 SEikControlInfo controlInfo; +00460 controlInfo.iControl = NULL; +00461 controlInfo.iTrailerTextId = 0; +00462 controlInfo.iFlags = 0; +00463 +00464 switch (aControlType) +00465 { +00466 case ESmileyControl: +00467 controlInfo.iControl = new(ELeave) CSmileyContainer; +00468 break; +00469 default: +00470 break; +00471 } +00472 return controlInfo; +00473 } +00474 +00476 // +00477 // -----> CExampleAppUi (implementation) +00478 // +00480 void CExampleAppUi::ConstructL() +00481 { +00482 // Allow base class (CEikAppUi) to perform necessary construction +00483 BaseConstructL(); +00484 // Construct the CMainWinControl which forms the main view +00485 // for this application. +00486 iMainWinControl=new(ELeave) CMainWinControl; +00487 iMainWinControl->ConstructL(ClientRect()); +00488 // The main window is added to the control stack (for key event +00489 // handling). +00490 AddToStackL(iMainWinControl); +00491 } +00492 +00493 +00494 CExampleAppUi::~CExampleAppUi() +00495 { +00496 RemoveFromStack(iMainWinControl); +00497 // Delete the main window +00498 delete iMainWinControl; +00499 } +00500 +00501 void CExampleAppUi::HandleCommandL(TInt aCommand) +00502 { +00503 // Handle the command generated by: +00504 // 1. menu item selection +00505 // 2. short-cut key press +00506 switch (aCommand) +00507 { +00508 // EXIT comand +00509 case EEikCmdExit: +00510 OnCmdExit(); +00511 break; +00512 case ECreateSmileyDialog: +00513 CSmileyDialog::RunDlgLD(); +00514 break; +00515 default : +00516 break; +00517 } +00518 } +00519 +00520 void CExampleAppUi::OnCmdExit() +00521 { +00522 CBaActiveScheduler::Exit(); +00523 } +00524 +00525 void CExampleAppUi::HandleModelChangeL() +00526 { +00527 } +00528 +00530 // +00531 // -----> CExampleDocument (implementation) +00532 // +00534 +00535 CExampleDocument::CExampleDocument(CEikApplication& aApp) +00536 : CEikDocument(aApp) +00537 {} +00538 +00539 CExampleDocument::~CExampleDocument() +00540 { +00541 } +00542 +00543 CExampleDocument* CExampleDocument::NewL(CEikApplication& aApp) +00544 { +00545 CExampleDocument* self=new(ELeave) CExampleDocument(aApp); +00546 CleanupStack::PushL(self); +00547 self->CreateModelL(); +00548 CleanupStack::Pop(); +00549 return self; +00550 } +00551 +00552 void CExampleDocument::ResetModelL() +00553 { +00554 CreateModelL(); +00555 } +00556 +00557 void CExampleDocument::CreateModelL() +00558 { +00559 } +00560 +00561 CEikAppUi* CExampleDocument::CreateAppUiL() +00562 { +00563 return(new(ELeave) CExampleAppUi); +00564 } +00565 +00566 void CExampleDocument::NewDocumentL() +00567 { +00568 ResetModelL(); +00569 } +00570 +00571 void CExampleDocument::StoreL(CStreamStore& /*aStore*/,CStreamDictionary& /*aStreamDic*/) const +00572 { +00573 } +00574 +00575 void CExampleDocument::RestoreL(const CStreamStore& /*aStore*/,const CStreamDictionary& /*aStreamDic*/) +00576 { +00577 } +00578 +00579 +00581 // +00582 // -----> CExampleApplication (implementation) +00583 // +00585 TUid CExampleApplication::AppDllUid() const +00586 { +00587 return(KUidExampleApp); +00588 } +00589 +00590 +00591 CApaDocument* CExampleApplication::CreateDocumentL() +00592 { +00593 return CExampleDocument::NewL(*this); +00594 } +00595 +00596 +00597 // +00598 // EXPORTed functions +00599 // +00600 +00601 +00602 LOCAL_C CApaApplication* NewApplication() +00603 { +00604 return new CExampleApplication; +00605 } +00606 +00607 GLDEF_C TInt E32Main() +00608 { +00609 return EikStart::RunApplication(NewApplication); +00610 } +00611 +00612 +00613 +00614 +00615 +