⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oandxappview.cpp

📁 Symbian OS C++ for Mobile Phones Volume 3 源码
💻 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 + -