examples/sfexamples/OandXViewArch/S60/src/oandxappview.cpp

00001 /*
00002 Copyright (c) 2002-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:  
00028 */
00029 
00030 #include <coemain.h>
00031 #include <gulutil.h>
00032 #include <e32keys.h>
00033 #include <aknviewappui.h>
00034 
00035 
00036 #include "OandXAppView.h"
00037 #include "OandXAppUi.h"
00038 #include "OandXController.h"
00039 #include "OandXEngine.h"
00040 #include <OandX.rsg>
00041 #include "OandX.pan"
00042 #include "OandX.hrh"
00043 #include "oandxdefs.h"
00044 
00045 COandXGameView* COandXGameView::NewLC()
00046     {
00047     COandXGameView* self = new ( ELeave ) COandXGameView();
00048     CleanupStack::PushL( self );
00049     self->ConstructL();
00050     return self;
00051     }
00052 
00053 COandXGameView::COandXGameView( )
00054     {
00055     }
00056 
00057 void COandXGameView::ConstructL()
00058     {
00059     BaseConstructL( R_OANDX_GAME_VIEW );
00060     iContainer = COandXAppViewContainer::NewL(ClientRect());
00061     iContainer->SetMopParent( this );
00062     }
00063 
00064 COandXGameView::~COandXGameView()
00065     {
00066     if (iGameViewStacked)
00067         {
00068         AppUi()->RemoveFromViewStack( *this, iContainer );
00069         }
00070     delete iContainer;
00071     }
00072 
00073 TUid COandXGameView::Id() const
00074     {
00075     return KUidOandXView;
00076     }
00077     
00078 void COandXGameView::HandleCommandL( TInt aCommand )
00079     {   
00080     switch ( aCommand )
00081         {
00082 
00083         case EAknSoftkeyBack:
00084             {
00085             AppUi()->HandleCommandL( EEikCmdExit );
00086             break;
00087             }
00088 
00089         default:
00090             {
00091             AppUi()->HandleCommandL( aCommand );
00092             break;
00093             }
00094         }
00095     }
00096 
00097 void COandXGameView::HandleViewRectChange()
00098     {
00099     if ( iContainer )
00100         {
00101         iContainer->SetRect(ClientRect());
00102         }
00103     }
00104     
00105 void COandXGameView::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane)
00106     {
00107         if (aResourceId != R_OANDX_GAME_MENU)
00108                 {
00109                 return;
00110                 }
00111         if (Controller().IsNewGame())
00112                 {
00113                 aMenuPane->DeleteMenuItem(EOandXNewGame);
00114                 if (!Controller().IsCrossTurn())
00115                         {
00116                         aMenuPane->SetItemTextL(EOandXFirstPlayer,R_OANDX_X_MOVES_FIRST);
00117                         }
00118                 }
00119         else
00120                 {
00121                 aMenuPane->DeleteMenuItem(EOandXFirstPlayer);
00122                 }
00123         }
00124 
00125 void COandXGameView::DoActivateL(const TVwsViewId& /*aPrevViewId*/,
00126                                  TUid /*aCustomMessageId*/,
00127                                  const TDesC8& /*aCustomMessage*/ )
00128     {
00129         __ASSERT_ALWAYS(!iGameViewStacked, Panic(EOandXControlAlreadyStacked));
00130     AppUi()->AddToStackL( *this, iContainer );
00131     iGameViewStacked = ETrue;
00132 
00133     iContainer->MakeVisible(ETrue);
00134     iContainer->DrawNow();
00135     }
00136 
00137 void COandXGameView::DoDeactivate()
00138     {
00139         __ASSERT_ALWAYS(iGameViewStacked, Panic(EOandXControlNotStacked));
00140     AppUi()->RemoveFromViewStack( *this, iContainer );
00141     iGameViewStacked = EFalse;
00142     
00143     iContainer->MakeVisible(EFalse);
00144     }
00145     
00146 COandXAppViewContainer* COandXGameView::Container()
00147     {
00148     return iContainer;
00149     }
00150 
00151 
00152 // O and X symbol-drawing control member functions
00153 
00154 void COandXSymbolControl::DrawSymbol(CWindowGc& aGc, const TRect& aRect, TBool aDrawCross) const
00155         {
00156         TRect drawRect(aRect);
00157         
00158         // Shrink by about 15%
00159         drawRect.Shrink(aRect.Width()/6,aRect.Height()/6); 
00160         
00161     // Pen size set to just over 10% of the overall shape's size
00162         TSize penSize(aRect.Width()/9,aRect.Height()/9);
00163         aGc.SetPenSize(penSize);
00164         aGc.SetPenStyle(CGraphicsContext::ESolidPen);
00165         
00166         if (aDrawCross)
00167                 {
00168                 aGc.SetPenColor(KRgbGreen);
00169                 
00170                 // Cosmetic reduction of cross size by half the line width
00171                 drawRect.Shrink(penSize.iWidth/2,penSize.iHeight/2);
00172                 
00173                 aGc.DrawLine(drawRect.iTl, drawRect.iBr);
00174                 TInt temp;
00175                 temp = drawRect.iTl.iX;
00176                 drawRect.iTl.iX = drawRect.iBr.iX;
00177                 drawRect.iBr.iX = temp;
00178                 aGc.DrawLine(drawRect.iTl, drawRect.iBr);
00179                 }
00180         else // draw a circle
00181                 {
00182                 aGc.SetPenColor(KRgbRed);
00183                 aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
00184                 aGc.DrawEllipse(drawRect);
00185                 }
00186         };
00187 
00188 // Tile member functions
00189 
00190 COandXTile::COandXTile()
00191         {
00192         }
00193         
00194 COandXTile::~COandXTile()
00195         {
00196         }
00197 
00198 void COandXTile::ConstructL(RWindow& aWindow)
00199         {
00200         SetContainerWindowL(aWindow);
00201         // No call to ActivateL() as the window is activated by its container
00202         }
00203 
00204 void COandXTile::Draw(const TRect& /*aRect*/) const
00205         {
00206         TTileState tileType;
00207         tileType = iCmdHandler->TileStatus(this);
00208 
00209         CWindowGc& gc = SystemGc();
00210         TRect rect = Rect();
00211         
00212         if (IsFocused())
00213                 {
00214                 gc.SetBrushColor(KRgbYellow);
00215                 }
00216         gc.Clear(rect);
00217         if (tileType!=ETileBlank)
00218                 {
00219                 DrawSymbol(gc, rect, tileType==ETileCross);
00220                 }
00221         }
00222 
00223 void  COandXTile::SetOwnerAndObserver(COandXAppViewContainer* aControl)
00224         {
00225         iCmdHandler = aControl;
00226         SetObserver(aControl);
00227         }
00228 
00229 void COandXTile::TryHitL()
00230         {
00231         if (iCmdHandler->TryHitSquareL(this))
00232                 {
00233                 DrawDeferred();
00234                 }
00235         }
00236 
00237 TKeyResponse COandXTile::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
00238         {
00239         TKeyResponse keyResponse = EKeyWasNotConsumed;
00240         if (aType!=EEventKey)
00241                 {
00242                 return keyResponse;
00243                 }
00244         switch (aKeyEvent.iCode)
00245                 {
00246         case EKeyOK:
00247                 TryHitL();
00248                 keyResponse = EKeyWasConsumed;
00249                 break;
00250         default:
00251                 keyResponse = EKeyWasNotConsumed;
00252                 break;          
00253                 }
00254         return keyResponse;
00255         }
00256 
00257 TCoeInputCapabilities COandXTile::InputCapabilities() const
00258         {
00259         return TCoeInputCapabilities::ENavigation;
00260         }
00261 
00262 void COandXTile::HandlePointerEventL(const TPointerEvent& aPointerEvent)
00263         {
00264         if (aPointerEvent.iType == TPointerEvent::EButton1Down)
00265                 {
00266                 TryHitL();
00267                 }
00268         }
00269 
00270 void COandXTile::FocusChanged(TDrawNow aDrawNow)
00271         {
00272         if (aDrawNow == EDrawNow)
00273                 {
00274                 DrawNow();
00275                 }
00276         }
00277 
00278 
00279 // Status window member functions
00280 
00281 COandXStatusWin* COandXStatusWin::NewL(RWindow& aWindow)
00282         {
00283         COandXStatusWin* self=new(ELeave) COandXStatusWin;
00284         CleanupStack::PushL(self);
00285         self->ConstructL(aWindow);
00286         CleanupStack::Pop();
00287         self->SetFocusing(EFalse);
00288         return self;
00289         }
00290 
00291 COandXStatusWin::COandXStatusWin()
00292         {
00293         }
00294         
00295 COandXStatusWin::~COandXStatusWin()
00296         {
00297         }
00298         
00299 void COandXStatusWin::ConstructL(RWindow& aWindow)
00300         {
00301         SetContainerWindowL(aWindow);
00302         // No call to ActivateL() as the window is activated by its container
00303         }
00304 
00305 void COandXStatusWin::Draw(const TRect& /*aRect*/) const
00306         {
00307         CWindowGc& gc = SystemGc();
00308         TRect boxRect = Rect();
00309         gc.Clear(boxRect);
00310         TInt boxHeight = boxRect.iBr.iY - boxRect.iTl.iY;
00311         boxRect.iTl.iX = boxRect.iBr.iX - boxHeight;
00312         DrawSymbol(gc, boxRect, Controller().IsCrossTurn());
00313         }
00314 
00315 
00316 // App View member functions
00317 
00318 #define KBorderWidth 10
00319 #define KLineWidth ((KTilesPerRow > KTilesPerCol ? KTilesPerRow : KTilesPerCol) > 4 ? 2 : 4)
00320 
00321 
00322 COandXAppViewContainer* COandXAppViewContainer::NewL(const TRect& aRect)
00323         {
00324         COandXAppViewContainer* self = new(ELeave) COandXAppViewContainer;
00325         CleanupStack::PushL(self);
00326         self->ConstructL(aRect);
00327         CleanupStack::Pop(self);
00328         return self;
00329         }
00330 
00331 COandXAppViewContainer::COandXAppViewContainer()
00335         {
00336         // empty.
00337         }
00338 
00339 COandXAppViewContainer::~COandXAppViewContainer()
00340         {
00341         for (TInt i=0; i<KNumberOfTiles; i++)
00342                 {
00343                 delete iTiles[i];
00344                 }
00345         iTiles.Close();
00346         delete iStatusWin;
00347         }
00348 
00349 void COandXAppViewContainer::ConstructL(const TRect& aRect)
00350         {
00351         // Create a window for this application view
00352         CreateWindowL();
00353 
00354         for (TInt i = 0; i < KNumberOfTiles; i++)
00355                 {
00356                 User::LeaveIfError(iTiles.Append(CreateTileL()));
00357                 }
00358         ComponentControl(0)->SetFocus(ETrue);
00359         iStatusWin = COandXStatusWin::NewL(Window());
00360 
00361         // Set the window's size
00362         SetRect(aRect); // needs to be after component creation - see SizeChanged()
00363         // Activate the window, which makes it ready to be drawn
00364         ActivateL();
00365         }
00366 
00367 COandXTile* COandXAppViewContainer::CreateTileL()
00368         {
00369         COandXTile* tile = new(ELeave) COandXTile;
00370         CleanupStack::PushL(tile);
00371         tile->ConstructL(Window());
00372         CleanupStack::Pop(); // tile
00373         tile->SetOwnerAndObserver(this);
00374         return tile;
00375         }
00376         
00377 void COandXAppViewContainer::SizeChanged()
00378         {
00379         __ASSERT_DEBUG(iTiles[KNumberOfTiles-1], Panic(EOandXNoTiles)); // all component tiles must already exist
00380 
00381         TRect rect = Rect();
00382         rect.iTl.iY = rect.iBr.iY - KStatusWinHeight;
00383         iStatusWin->SetRect(rect);
00384         rect = Rect();
00385         rect.iBr.iY -= KStatusWinHeight;
00386         TSize controlSize = rect.Size();
00387         TSize tileSize;
00388         tileSize.iWidth=2*((controlSize.iWidth-2*KBorderWidth-(KTilesPerRow-1)*KLineWidth)/(2*KTilesPerRow));
00389         tileSize.iHeight=2*((controlSize.iHeight-2*KBorderWidth-(KTilesPerCol-1)*KLineWidth)/(2*KTilesPerCol));
00390         iTileSide = tileSize.iWidth < tileSize.iHeight ? tileSize.iWidth :tileSize.iHeight;
00391         TSize boardSize;
00392         boardSize.iWidth = KTilesPerRow*iTileSide + (KTilesPerRow-1)*KLineWidth;
00393         boardSize.iHeight = KTilesPerCol*iTileSide + (KTilesPerCol-1)*KLineWidth;
00394         iBoardRect.iTl.iX = (controlSize.iWidth - boardSize.iWidth)/2;
00395         iBoardRect.iTl.iY = (controlSize.iHeight - boardSize.iHeight)/2;
00396         iBoardRect.iBr.iX = iBoardRect.iTl.iX + boardSize.iWidth;
00397         iBoardRect.iBr.iY = iBoardRect.iTl.iY + boardSize.iHeight;
00398         iBorderRect = iBoardRect;
00399         iBorderRect.Grow(KBorderWidth,KBorderWidth);
00400         
00401         for (TInt i=0; i<KNumberOfTiles; i++)
00402                 {
00403                 TInt row = i / KTilesPerRow;
00404                 TInt col = i % KTilesPerRow;
00405                 TRect tileRect;
00406                 tileRect.iTl.iX = iBoardRect.iTl.iX + col * (iTileSide + KLineWidth);
00407                 tileRect.iTl.iY = iBoardRect.iTl.iY + row * (iTileSide + KLineWidth);
00408                 tileRect.iBr.iX = tileRect.iTl.iX + iTileSide;
00409                 tileRect.iBr.iY = tileRect.iTl.iY + iTileSide;
00410                 ComponentControl(i)->SetRect(tileRect);
00411                 }
00412         }
00413         
00414 void COandXAppViewContainer::ResetView()
00415         {
00416         MoveFocusTo(0);
00417         DrawNow();
00418         }
00419 
00420 
00421 void COandXAppViewContainer::Draw(const TRect& /*aRect*/) const
00422         {
00423         CWindowGc& gc = SystemGc();
00424         TRect rect = Rect();
00425         
00426         // Draw outside the border
00427         gc.SetPenStyle(CGraphicsContext::ENullPen);
00428         gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
00429         gc.SetBrushColor(KRgbWhite);
00430         DrawUtils::DrawBetweenRects(gc, rect, iBorderRect);
00431         
00432         // Draw a border around the board
00433         gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
00434         gc.SetBrushColor(KRgbGray);
00435         DrawUtils::DrawBetweenRects(gc, iBorderRect, iBoardRect);
00436         
00437         //Draw the first vertical line
00438         gc.SetBrushColor(KRgbBlack);
00439         TRect line;
00440         line.iTl.iX = iBoardRect.iTl.iX + iTileSide;
00441         line.iTl.iY = iBoardRect.iTl.iY;
00442         line.iBr.iX = line.iTl.iX + KLineWidth;
00443         line.iBr.iY = iBoardRect.iBr.iY;
00444         gc.DrawRect(line);
00445         // Draw the remaining (KTilesPerRow-2) vertical lines
00446         for (TInt i = 0; i < KTilesPerRow - 2; i++)
00447                 {
00448                 line .iTl.iX += iTileSide + KLineWidth;
00449                 line .iBr.iX += iTileSide + KLineWidth;
00450                 gc.DrawRect(line);
00451                 }
00452         // Draw the first horizontal line
00453         line.iTl.iX = iBoardRect.iTl.iX;
00454         line.iTl.iY = iBoardRect.iTl.iY + iTileSide;
00455         line.iBr.iX = iBoardRect.iBr.iX;
00456         line.iBr.iY = line.iTl.iY + KLineWidth;
00457         gc.DrawRect(line);
00458         // Draw the remaining (KTilesPerCol -2) horizontal lines
00459         for (TInt i = 0; i < KTilesPerCol - 2; i++)
00460                 {
00461                 line .iTl.iY += iTileSide + KLineWidth;
00462                 line .iBr.iY += iTileSide + KLineWidth;
00463                 gc.DrawRect(line);
00464                 }
00465         }
00466 
00467 
00468 TInt COandXAppViewContainer::CountComponentControls() const
00469         {
00470         return KNumberOfTiles +1;
00471         }
00472 
00473 CCoeControl* COandXAppViewContainer::ComponentControl(TInt aIndex) const
00474         {
00475         if (aIndex==KNumberOfTiles)
00476                 {
00477                 return iStatusWin;
00478                 }
00479         else
00480                 {
00481                 return const_cast<COandXTile*>(iTiles[aIndex]);
00482                 }
00483         }
00484 
00485 TKeyResponse COandXAppViewContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
00486         {
00487         TKeyResponse keyResponse = EKeyWasNotConsumed;
00488         if (aType!=EEventKey)
00489                 {
00490                 return keyResponse;
00491                 }
00492         TInt index = IdOfFocusControl();
00493         switch (aKeyEvent.iCode)
00494                 {
00495         case EKeyLeftArrow: // check not in first column
00496                 if (index % KTilesPerRow)
00497                         {
00498                         MoveFocusTo(index-1);
00499                         keyResponse = EKeyWasConsumed;
00500                         }
00501                 break;
00502         case EKeyRightArrow: // check not in last column
00503                 if ((index % KTilesPerRow) < KTilesPerRow - 1)
00504                         {
00505                         MoveFocusTo(index+1);
00506                         keyResponse = EKeyWasConsumed;
00507                         }
00508                 break;
00509         case EKeyUpArrow: // check not on top row
00510                 if (index >= KTilesPerRow)
00511                         {
00512                         MoveFocusTo(index-KTilesPerRow);
00513                         keyResponse = EKeyWasConsumed;
00514                         }
00515                 break;
00516         case EKeyDownArrow: // check not in bottom row
00517                 if (index < KNumberOfTiles - KTilesPerRow)
00518                         {
00519                         MoveFocusTo(index+KTilesPerRow);
00520                         keyResponse = EKeyWasConsumed;
00521                         }
00522                 break;
00523         default:
00524                 keyResponse = ComponentControl(index)->OfferKeyEventL(aKeyEvent,aType);
00525                 break;
00526                 }
00527         return keyResponse;
00528         }
00529 
00530 TInt COandXAppViewContainer::IdOfFocusControl()
00531         {
00532         TInt ret = -1;
00533         for (TInt i=0; i<KNumberOfTiles; i++)
00534                 {
00535                 if (ComponentControl(i)->IsFocused())
00536                         {
00537                         ret = i;
00538                         break;
00539                         }
00540                 }
00541         __ASSERT_ALWAYS(ret>=0, Panic(EOandXNoTileWithFocus));
00542         return ret;
00543         }
00544         
00545 void COandXAppViewContainer::SwitchFocus(TInt aFromIndex, CCoeControl* aToControl)
00546         {
00547         ComponentControl(aFromIndex)->SetFocus(EFalse, EDrawNow);
00548         aToControl->SetFocus(ETrue, EDrawNow);
00549         }
00550         
00551 void COandXAppViewContainer::MoveFocusTo(const TInt index)
00552         {
00553         TInt oldIndex = IdOfFocusControl();
00554         if (index!= oldIndex)
00555                 {
00556                 SwitchFocus(oldIndex, ComponentControl(index));
00557                 }
00558         }
00559 
00560 
00561 void COandXAppViewContainer::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType)
00562         {
00563         switch (aEventType)
00564                 {
00565         case EEventRequestFocus:
00566                 SwitchFocus(IdOfFocusControl(), aControl);
00567                 break;
00568         default:
00569                 break;
00570                 }
00571         }
00572 
00573 TBool COandXAppViewContainer::TryHitSquareL(const COandXTile* aControl)
00574         {
00575         return Controller().HitSquareL(Index(aControl));
00576         }
00577 
00578 TTileState COandXAppViewContainer::TileStatus(const COandXTile* aControl) const
00579         {
00580         return Engine().TileStatus(Index(aControl));
00581         }
00582 
00583 void COandXAppViewContainer::ShowTurn()
00584         {
00585         iStatusWin->DrawDeferred();
00586         }

Generated by  doxygen 1.6.2