?? oandxappview.cpp
字號:
// Copyright (c) 2004 - 2006, Symbian Software Ltd. All rights reserved.
#include <coemain.h>
#include <gulutil.h>
#include <e32keys.h>
#include "OandXAppView.h"
#include "OandXAppUi.h"
#include "OandX.pan"
#include "oandxdefs.h"
#include "oandxcontroller.h"
#include "oandxengine.h"
// O and X symbol-drawing control member functions
void COandXSymbolControl::DrawSymbol(CWindowGc& aGc, TRect& aRect, TBool aDrawCross) const
{
TSize size;
size.SetSize(aRect.iBr.iX- aRect.iTl.iX, aRect.iBr.iY - aRect.iTl.iY);
aRect.Shrink(size.iWidth/6,size.iHeight/6); // Shrink by about 15%
aGc.SetPenStyle(CGraphicsContext::ESolidPen);
size.iWidth /= 9; // Pen size set to just over 10% of the shape's size
size.iHeight /= 9;
aGc.SetPenSize(size);
if (aDrawCross)
{
aGc.SetPenColor(KRgbGreen);
aRect.Shrink(size.iWidth/2,size.iHeight/2); // Cosmetic reduction of cross size by half the line width
aGc.DrawLine(aRect.iTl, aRect.iBr);
TInt temp;
temp = aRect.iTl.iX;
aRect.iTl.iX = aRect.iBr.iX;
aRect.iBr.iX = temp;
aGc.DrawLine(aRect.iTl, aRect.iBr);
}
else // draw a circle
{
aGc.SetPenColor(KRgbRed);
aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
aGc.DrawEllipse(aRect);
}
};
COandXTile* COandXTile::NewL(const CCoeControl* aContainer)
/**
Factory function allocates new initialized instance of COandXTile.
@param aContainer Control which will contain the new component control.
@return New instance of COandXTile which will be owned by
the caller.
*/
{
COandXTile* self = new(ELeave) COandXTile;
CleanupStack::PushL(self);
self->ConstructL(aContainer);
CleanupStack::Pop(self);
return self;
}
COandXTile::COandXTile()
/**
This private constructor is defined to ensure it is
implemented exactly once, and to ensure all instances
are allocated via NewL.
*/
{
// empty.
}
void COandXTile::ConstructL(const CCoeControl* aContainer)
/**
Perform secondary initialization by registering this control
as a component of the supplied container control.
@param aContainer Control which will own the new component control.
*/
{
SetContainerWindowL(*aContainer);
}
void COandXTile::Draw(const TRect& aRect) const
/**
Override CCoeControl by redrawing this tile. This
draws a blank square, possibly with a nought or cross on it.
@param aRect Area of the control which needs to be redrawn.
This is not used, and the entire control is
redrawn.
*/
{
(void) aRect;
TInt tileType = iAppView->SquareStatus(this);
CWindowGc& gc = SystemGc();
TRect rect = Rect();
if (IsFocused())
{
gc.SetBrushColor(KRgbYellow);
}
gc.Clear(rect);
if (tileType!=ETileBlank)
{
DrawSymbol(gc, rect, tileType==ETileCross);
}
}
void COandXTile::SetOwnerAndObserver(COandXAppView* aControl)
{
iAppView = aControl;
SetObserver(aControl);
}
void COandXTile::TryHitL()
{
iAppView->TryHitSquareL(this);
}
TKeyResponse COandXTile::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
TKeyResponse keyResponse = EKeyWasNotConsumed;
if (aType!=EEventKey)
{
return keyResponse;
}
switch (aKeyEvent.iCode)
{
case EKeyOK:
TryHitL();
keyResponse = EKeyWasConsumed;
break;
default:
keyResponse = EKeyWasNotConsumed;
break;
}
return keyResponse;
}
TCoeInputCapabilities COandXTile::InputCapabilities() const
{
return TCoeInputCapabilities::ENavigation;
}
void COandXTile::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
if (aPointerEvent.iType == TPointerEvent::EButton1Down)
{
TryHitL();
}
}
void COandXTile::FocusChanged(TDrawNow aDrawNow)
{
if (aDrawNow == EDrawNow)
{
DrawNow();
}
}
// Status window
COandXStatusWin* COandXStatusWin::NewL(RWindow& aWindow)
{
COandXStatusWin* self=new(ELeave) COandXStatusWin;
CleanupStack::PushL(self);
self->ConstructL(aWindow);
CleanupStack::Pop(self);
return self;
}
COandXStatusWin::COandXStatusWin()
{
}
void COandXStatusWin::ConstructL(RWindow& aWindow)
{
SetContainerWindowL(aWindow);
// No call to ActivateL() as the window is activated by its container
}
void COandXStatusWin::Draw(const TRect& /*aRect*/) const
{
CWindowGc& gc = SystemGc();
TRect boxRect = Rect();
gc.Clear(boxRect);
TInt boxHeight = boxRect.iBr.iY - boxRect.iTl.iY;
boxRect.iTl.iX = boxRect.iBr.iX - boxHeight;
TBool crossTurn = Controller().IsCrossTurn();
DrawSymbol(gc, boxRect, crossTurn);
}
// App View member functions
#define KBorderWidth 10
#define KLineWidth ((KTilesPerRow > KTilesPerCol ? KTilesPerRow : KTilesPerCol) > 4 ? 2 : 4)
COandXAppView* COandXAppView::NewL(const TRect& aRect)
{
COandXAppView* self = new(ELeave) COandXAppView;
CleanupStack::PushL(self);
self->ConstructL(aRect);
CleanupStack::Pop(self);
return self;
}
COandXAppView::COandXAppView()
/**
*/
{
// empty.
}
COandXAppView::~COandXAppView()
{
iTiles.ResetAndDestroy();
delete iStatusWin;
}
void COandXAppView::ConstructL(const TRect& aRect)
{
// Create a window for this application view
CreateWindowL();
for (TInt i = 0; i < KNumberOfTiles; i++)
{
COandXTile* tile = CreateTileL();
CleanupStack::PushL(tile); // in case AppendL fails
iTiles.AppendL(tile);
CleanupStack::Pop(tile);
}
ComponentControl(0)->SetFocus(ETrue);
iStatusWin = COandXStatusWin::NewL(Window());
// Set the window's size
SetRect(aRect); // needs to be after component creation - see SizeChanged()
// Activate the window, which makes it ready to be drawn
ActivateL();
}
COandXTile* COandXAppView::CreateTileL()
{
COandXTile* tile = COandXTile::NewL(this);
tile->SetOwnerAndObserver(this);
return tile;
}
void COandXAppView::SizeChanged()
{
__ASSERT_DEBUG(iTiles[KNumberOfTiles-1], Panic(EOandXNoTiles)); // all component tiles must already exist
TRect rect = Rect();
rect.iTl.iY = rect.iBr.iY - KStatusWinHeight;
iStatusWin->SetRect(rect);
rect = Rect();
rect.iBr.iY -= KStatusWinHeight;
TSize controlSize = rect.Size();
TSize tileSize;
tileSize.iWidth=2*((controlSize.iWidth-2*KBorderWidth-(KTilesPerRow-1)*KLineWidth)/(2*KTilesPerRow));
tileSize.iHeight=2*((controlSize.iHeight-2*KBorderWidth-(KTilesPerCol-1)*KLineWidth)/(2*KTilesPerCol));
iTileSide = tileSize.iWidth < tileSize.iHeight ? tileSize.iWidth :tileSize.iHeight;
TSize boardSize;
boardSize.iWidth = KTilesPerRow*iTileSide + (KTilesPerRow-1)*KLineWidth;
boardSize.iHeight = KTilesPerCol*iTileSide + (KTilesPerCol-1)*KLineWidth;
iBoardRect.iTl.iX = (controlSize.iWidth - boardSize.iWidth)/2;
iBoardRect.iTl.iY = (controlSize.iHeight - boardSize.iHeight)/2;
iBoardRect.iBr.iX = iBoardRect.iTl.iX + boardSize.iWidth;
iBoardRect.iBr.iY = iBoardRect.iTl.iY + boardSize.iHeight;
iBorderRect = iBoardRect;
iBorderRect.Grow(KBorderWidth,KBorderWidth);
for (TInt i=0; i<KNumberOfTiles; i++)
{
TInt row = i / KTilesPerRow;
TInt col = i % KTilesPerRow;
TRect tileRect;
tileRect.iTl.iX = iBoardRect.iTl.iX + col * (iTileSide + KLineWidth);
tileRect.iTl.iY = iBoardRect.iTl.iY + row * (iTileSide + KLineWidth);
tileRect.iBr.iX = tileRect.iTl.iX + iTileSide;
tileRect.iBr.iY = tileRect.iTl.iY + iTileSide;
ComponentControl(i)->SetRect(tileRect);
}
}
void COandXAppView::Draw(const TRect& /*aRect*/) const
{
CWindowGc& gc = SystemGc();
// if no current game then print a message and return
if (! Controller().DrawableGame())
{
CWindowGc& gc = SystemGc();
gc.SetPenColor(KRgbBlack);
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetBrushColor(KRgbWhite);
const CFont* pf = CEikonEnv::Static()->DenseFont();
gc.UseFont(pf);
// write message about 1/4 way down application view
_LIT(KNoGameMsg, "No current game.");
const TRect rFull = Rect();
TInt height = rFull.Height();
TInt useBase = (height / 4) + pf->BaselineOffsetInPixels();
gc.DrawText(KNoGameMsg, rFull, useBase, CGraphicsContext::ECenter);
gc.DiscardFont();
return;
}
TRect rect = Rect();
// Draw outside the border
gc.SetPenStyle(CGraphicsContext::ENullPen);
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetBrushColor(KRgbWhite);
DrawUtils::DrawBetweenRects(gc, rect, iBorderRect);
// Draw a border around the board
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetBrushColor(KRgbGray);
DrawUtils::DrawBetweenRects(gc, iBorderRect, iBoardRect);
//Draw the first vertical line
gc.SetBrushColor(KRgbBlack);
TRect line;
line.iTl.iX = iBoardRect.iTl.iX + iTileSide;
line.iTl.iY = iBoardRect.iTl.iY;
line.iBr.iX = line.iTl.iX + KLineWidth;
line.iBr.iY = iBoardRect.iBr.iY;
gc.DrawRect(line);
TInt i;
// Draw the remaining (KTilesPerRow-2) vertical lines
for (i = 0; i < KTilesPerRow - 2; i++)
{
line .iTl.iX += iTileSide + KLineWidth;
line .iBr.iX += iTileSide + KLineWidth;
gc.DrawRect(line);
}
// Draw the first horizontal line
line.iTl.iX = iBoardRect.iTl.iX;
line.iTl.iY = iBoardRect.iTl.iY + iTileSide;
line.iBr.iX = iBoardRect.iBr.iX;
line.iBr.iY = line.iTl.iY + KLineWidth;
gc.DrawRect(line);
// Draw the remaining (KTilesPerCol -2) horizontal lines
for (i = 0; i < KTilesPerCol - 2; i++)
{
line .iTl.iY += iTileSide + KLineWidth;
line .iBr.iY += iTileSide + KLineWidth;
gc.DrawRect(line);
}
}
TInt COandXAppView::CountComponentControls() const
{
return KNumberOfTiles +1;
}
CCoeControl* COandXAppView::ComponentControl(TInt aIndex) const
{
if (aIndex==KNumberOfTiles)
{
return iStatusWin;
}
else
{
return const_cast<COandXTile*>(iTiles[aIndex]);
}
}
TKeyResponse COandXAppView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
TKeyResponse keyResponse = EKeyWasNotConsumed;
if (aType!=EEventKey)
{
return keyResponse;
}
TInt index = IdOfFocusControl();
switch (aKeyEvent.iCode)
{
case EKeyLeftArrow: // check not in first column
if (index % KTilesPerRow)
{
MoveFocusTo(index-1);
keyResponse = EKeyWasConsumed;
}
break;
case EKeyRightArrow: // check not in last column
if ((index % KTilesPerRow) < KTilesPerRow - 1)
{
MoveFocusTo(index+1);
keyResponse = EKeyWasConsumed;
}
break;
case EKeyUpArrow: // check not on top row
if (index >= KTilesPerRow)
{
MoveFocusTo(index-KTilesPerRow);
keyResponse = EKeyWasConsumed;
}
break;
case EKeyDownArrow: // check not in bottom row
if (index < KNumberOfTiles - KTilesPerRow)
{
MoveFocusTo(index+KTilesPerRow);
keyResponse = EKeyWasConsumed;
}
break;
default:
keyResponse = ComponentControl(index)->OfferKeyEventL(aKeyEvent,aType);
break;
}
return keyResponse;
}
TInt COandXAppView::IdOfFocusControl()
{
TInt ret = -1;
for (TInt i=0; i<KNumberOfTiles; i++)
{
if (ComponentControl(i)->IsFocused())
{
ret = i;
break;
}
}
__ASSERT_ALWAYS(ret>=0, Panic(EOandXNoTileWithFocus));
return ret;
}
void COandXAppView::SwitchFocus(TInt aFromIndex, CCoeControl* aToControl)
{
ComponentControl(aFromIndex)->SetFocus(EFalse, EDrawNow);
aToControl->SetFocus(ETrue, EDrawNow);
}
void COandXAppView::MoveFocusTo(const TInt index)
{
TInt oldIndex = IdOfFocusControl();
if (index!= oldIndex)
{
SwitchFocus(oldIndex, ComponentControl(index));
}
}
void COandXAppView::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType)
{
switch (aEventType)
{
case EEventRequestFocus:
SwitchFocus(IdOfFocusControl(), aControl);
break;
default:
break;
}
}
void COandXAppView::TryHitSquareL(const COandXTile* aControl)
{
TInt tileIndex = Index(aControl);
Controller().HitSquareL(tileIndex);
}
TInt COandXAppView::SquareStatus(const COandXTile* aControl)
{
return Engine().SquareStatus(Index(aControl));
}
// implement MOandXGameObserver
void COandXAppView::ResetView()
{
TBool drawable = Controller().DrawableGame();
for (TInt i = 0; i < KNumberOfTiles; ++i)
ComponentControl(i)->MakeVisible(drawable);
iStatusWin->MakeVisible(drawable);
if (drawable)
MoveFocusTo(0);
DrawDeferred();
}
void COandXAppView::RedrawSquare(TInt aIndex)
{
ComponentControl(aIndex)->DrawDeferred();
}
void COandXAppView::RedrawCurrentPlayer()
{
iStatusWin->DrawDeferred();
}
void COandXAppView::ReportWinner(TInt aWinner)
{
TRAP_IGNORE(OandXAppUi()->ReportWinnerL(aWinner));
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -