diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_custom_controls_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_custom_controls_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,613 +0,0 @@ - -
-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 -