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

📄 bossview.cpp

📁 Symbian C++ scmp.zip
💻 CPP
字号:
// bossview.cpp
//
// Copyright (c) 1998 Symbian Ltd.  All rights reserved.

#include "bossview.h"
#include "bosseng.h"

#include <coemain.h>

const TInt KBossScrollIncrements=4; // 4 increments
#define KBossScrollTime TTimeIntervalMicroSeconds32(50000) // 0.05 sec

/*
	CBossScroller - private definition
*/

class CBossScroller : public CActive
	{
public:
	// construct/destruct
	CBossScroller(CBossView* aView, RWindow& aWindow);
	void ConstructL();
	~CBossScroller();
	// requester functions
	void StartL(TInt aOldBlankRow, TInt aOldBlankCol, TInt aNewBlankRow, TInt aNewBlankCol);
private: // from CActive
	void DoCancel();
	void RunL();
private:
	void DoIncrement(); // do a scrolling increment and wait for next
private:
	RTimer iTimer;
	CBossView* iView;
	RWindow& iWindow;
	// incremental scrolling calculations
	TInt iOldBlankRow;
	TInt iOldBlankCol;
	TInt iNewBlankRow;
	TInt iNewBlankCol;
	TRect iBoundingRect;
	TPoint iVectorNeeded;
	TInt iScalarNeeded;
	TInt iScalarIncrement;
	TPoint iUnitVector;
	TInt iScalarDone;
	};

/*
	CBossView
*/

EXPORT_C CBossView::CBossView(TBossPuzzle* aModel)
	: iModel(aModel)
	{
	}

EXPORT_C CBossView::CBossView()
	{
	}

EXPORT_C void CBossView::ConstructL(MGraphicsDeviceMap* aDeviceMap)
	{
	SetDeviceMapL(aDeviceMap);
	}

CBossView::~CBossView()
	{
	SetDeviceMapL(0);
	}

// constants

#define KBossTileSizeInTwips TPoint(480,480) // 1/3 inch square
#define KBossTileBorderInTwips TPoint(40,40) // 2 points
#define KBossBoardMarginInTwips TPoint(120,120) // 6 points = 1/12 inch

// handy utility function
TPoint operator*(TInt aScale, const TPoint& aPoint)
	{ return TPoint(aScale*aPoint.iX, aScale*aPoint.iY); }

EXPORT_C void CBossView::SetDeviceMapL(MGraphicsDeviceMap* aDeviceMap)
	{
	//constant declarations
	_LIT(KFontArial,"Arial");

	// check for significant change
	const TPoint p(10000,10000);
	if (iDeviceMap && aDeviceMap && aDeviceMap->TwipsToPixels(p)==iDeviceMap->TwipsToPixels(p))
		return;
	// release old font
	ReleaseTileFont();
	// set new device map
	iDeviceMap=aDeviceMap;
	// quit if no map
	if (!iDeviceMap)
		return;
	// tile size
	iTileSizeInPixels=iDeviceMap->TwipsToPixels(KBossTileSizeInTwips);
	iTileBorderInPixels=iDeviceMap->TwipsToPixels(KBossTileBorderInTwips);
	// board margin and size
	iBoardMarginInPixels=iDeviceMap->TwipsToPixels(KBossBoardMarginInTwips);
	iBoardSizeInPixels=4*iTileSizeInPixels+2*iBoardMarginInPixels;
	TFontSpec bossTileFontSpec (KFontArial, 12*20); // 12 points = 1/6 inch
	bossTileFontSpec.iTypeface.SetIsProportional(ETrue); // Arial is proportional 
	// tile font 
	User::LeaveIfError(iDeviceMap->GetNearestFontInTwips(iTileFont,bossTileFontSpec));
	}

void CBossView::GetBoardRect(TRect& aBoardRect) const
	{
	aBoardRect=TRect(iTopLeft, iBoardSizeInPixels.AsSize());
	}

void CBossView::DrawBackground(const TRect& aRect) const
	{
	TRect boardOuterRect;
	GetBoardRect(boardOuterRect);
	iGc->SetPenStyle(CGraphicsContext::ENullPen);
	iGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	iGc->SetBrushColor(KRgbGray);
	if (boardOuterRect.iBr.iX < aRect.iBr.iX) // fill to the right
		{
		TRect r(TPoint(boardOuterRect.iBr.iX, boardOuterRect.iTl.iY),
			TPoint(aRect.iBr.iX, boardOuterRect.iBr.iY));
		iGc->DrawRect(r);
		}
	if (boardOuterRect.iBr.iY < aRect.iBr.iY) // fill below, and below-right if needed
		{
		TRect r(TPoint(boardOuterRect.iTl.iX, boardOuterRect.iBr.iY), aRect.iBr);
		iGc->DrawRect(r);
		}
	}

void CBossView::DrawBoard() const
	{
	// calculate rectangle to draw into
	TRect boardOuterRect;
	GetBoardRect(boardOuterRect);
	TRect boardInnerRect=boardOuterRect;
	boardInnerRect.Shrink(iBoardMarginInPixels.AsSize()-TSize(1,1));
	// draw board border
	iGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	iGc->SetBrushColor(KRgbDarkGray);
	iGc->SetPenStyle(CGraphicsContext::ENullPen);
	iGc->DrawRect(TRect(boardOuterRect.iTl, TPoint(boardOuterRect.iBr.iX, boardInnerRect.iTl.iY)));
	iGc->DrawRect(TRect(TPoint(boardOuterRect.iTl.iX,boardInnerRect.iBr.iY),boardOuterRect.iBr));
	iGc->DrawRect(TRect(TPoint(boardOuterRect.iTl.iX,boardInnerRect.iTl.iY),TPoint(boardInnerRect.iTl.iX,boardInnerRect.iBr.iY)));
	iGc->DrawRect(TRect(TPoint(boardInnerRect.iBr.iX,boardInnerRect.iTl.iY),TPoint(boardOuterRect.iBr.iX,boardInnerRect.iBr.iY)));
	// draw highlights
	iGc->SetBrushStyle(CGraphicsContext::ENullBrush);
	iGc->SetPenStyle(CGraphicsContext::ESolidPen);
	iGc->SetPenColor(KRgbBlack);
	iGc->DrawRect(boardOuterRect);
	iGc->SetPenColor(KRgbWhite);
	iGc->DrawRect(boardInnerRect);
	}

void CBossView::GetTileRect(TRect& aTileRect, TInt aRow, TInt aCol) const
	{
	TPoint tileTopLeft=iTopLeft+iBoardMarginInPixels;
	aTileRect=
		TRect(
			tileTopLeft+TPoint(aCol*iTileSizeInPixels.iX,aRow*iTileSizeInPixels.iY),
			iTileSizeInPixels.AsSize()
			);
	}

TInt CBossView::GetTileFromXY(const TPoint& aPoint, TInt& aRow, TInt& aCol)
	{
	// a truly crass implementation - scan all tiles - should optimize to exploit obvious geometry
	for (aRow=0; aRow<4; aRow++)
		{
		for (aCol=0; aCol<4; aCol++)
			{
			TRect tileRect;
			GetTileRect(tileRect, aRow, aCol);
			if (tileRect.Contains(aPoint))
				return KErrNone;
			}
		}
	return KErrNotFound;
	}

void CBossView::DrawTile(TInt aRow, TInt aCol) const
	{ 
	//constant declarations
	_LIT(KNumFormat,"%d");

	// tile or blank
	TRect tileRect;
	GetTileRect(tileRect, aRow, aCol);
	if (iModel->Tile(aRow,aCol)!=0) // real tile
		{
		iGc->UseFont(iTileFont);
		// draw rectangle
		iGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
		iGc->SetBrushColor(KRgbGray);
		iGc->SetPenStyle(CGraphicsContext::ESolidPen);
		iGc->SetPenColor(KRgbBlack);
		iGc->DrawRect(tileRect);
		iGc->SetPenColor(KRgbWhite);
		iGc->DrawLine(TPoint(tileRect.iTl.iX,tileRect.iBr.iY-2),tileRect.iTl);
		iGc->DrawLine(tileRect.iTl,TPoint(tileRect.iBr.iX-1,tileRect.iTl.iY));
		tileRect.Shrink(iTileBorderInPixels.AsSize());
		iGc->SetBrushColor(KRgbWhite);
		iGc->SetPenColor(KRgbBlack);
		// draw number
		TInt ascent=
				(tileRect.Height() - iTileFont->HeightInPixels())/2 +
					iTileFont->AscentInPixels();
		// draw text in rectangle
		TBuf<2> number;
		number.Format(KNumFormat,TInt(iModel->Tile(aRow,aCol)));
		iGc->DrawText(number, tileRect, ascent, CGraphicsContext::ECenter, 0);
		iGc->DiscardFont();
		}
	else // blank
		{
		iGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
		iGc->SetBrushColor(KRgbGray);
		iGc->SetPenStyle(CGraphicsContext::ENullPen);
		iGc->DrawRect(tileRect);
		}
	}

EXPORT_C void CBossView::GetOriginalSizeInTwips(TSize& aSize) const
	{
	TPoint size=4*KBossTileSizeInTwips+2*KBossBoardMarginInTwips;
	aSize=size.AsSize();
	}

EXPORT_C TSize CBossView::GetSizeInPixels() const
	{
	return iBoardSizeInPixels.AsSize();
	}

void CBossView::ReleaseTileFont()
	{
	if (iTileFont)
		{
		iDeviceMap->ReleaseFont(iTileFont);
		iTileFont=0;
		}
	}

EXPORT_C void CBossView::Draw(CGraphicsContext& aGc, const TRect& aRect, const TPoint& aTopLeft) const
	{
	// remember values
	CBossView* mutableThis=(CBossView*) this;
	mutableThis->iGc=&aGc;
	mutableThis->iTopLeft=aTopLeft;
	// draw components
	DrawBackground(aRect);
	DrawBoard();
	for (TInt row=0; row<4; row++)
		for (TInt col=0; col<4; col++)
			DrawTile(row,col);
	}

/*
	CBossControl
*/

EXPORT_C CBossControl::CBossControl(TBossPuzzle* aModel, CBossView* aView, MBossControlObserver* aObserver)
	: iModel(aModel), iView(aView), iObserver(aObserver)
	{
	}

EXPORT_C CBossControl::CBossControl()
	{
	}

EXPORT_C void CBossControl::ConstructL(const CCoeControl* aParent, const TRect& aRect)
	{
	// create window - a lodger control
	CreateWindowL(aParent);
	SetRect(aRect);
	// create scroller
	iScroller=new (ELeave) CBossScroller(iView, Window());
	iScroller->ConstructL();
	// go for it
	ActivateL();
	}

CBossControl::~CBossControl()
	{
	delete iScroller;
	}

void CBossControl::Draw(const TRect& /* aRect */) const
	{
	// clear board altogether
	CWindowGc& gc=SystemGc();
	iView->Draw(gc, Rect(), TPoint(0,0));
   	}

void CBossControl::HandlePointerEventL(const TPointerEvent& aPointerEvent)
	{
	switch (aPointerEvent.iType)
		{
	case TPointerEvent::EButton1Down:
		{
		TInt row, col;
		TInt err=iView->GetTileFromXY(aPointerEvent.iPosition, row, col);
		if (err!=KErrNone)
			break;
		iObserver->BCOMove(row, col);
		}
	default:
		break;
		}
	}

TKeyResponse CBossControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
	{
	if (aType!=EEventKey)
		return EKeyWasNotConsumed;
	switch(aKeyEvent.iCode)
		{
	case EKeyLeftArrow:
		iObserver->BCOMove(TBossPuzzle::ELeft);
		break;
	case EKeyRightArrow:
		iObserver->BCOMove(TBossPuzzle::ERight);
		break;
	case EKeyUpArrow:
		iObserver->BCOMove(TBossPuzzle::EUp);
		break;
	case EKeyDownArrow:
		iObserver->BCOMove(TBossPuzzle::EDown);
		break;
	default:
		return EKeyWasNotConsumed;
		}
	return EKeyWasConsumed;
	}

EXPORT_C void CBossControl::MoveTile(TInt aOldBlankRow, TInt aOldBlankCol, TInt aNewBlankRow, TInt aNewBlankCol) const
	{
	iScroller->StartL(aOldBlankRow, aOldBlankCol, aNewBlankRow, aNewBlankCol);
	}

EXPORT_C void CBossControl::FinishMove() const
	{
	iScroller->Cancel();
	}

/*
	CBossScroller
*/

CBossScroller::CBossScroller(CBossView* aView, RWindow& aWindow)
	: CActive(CActive::EPriorityStandard), iView(aView), iWindow(aWindow)
	{
	CActiveScheduler::Add(this);
	}

void CBossScroller::ConstructL()
	{
	User::LeaveIfError(iTimer.CreateLocal());
	}

CBossScroller::~CBossScroller()
	{
	Cancel();
	iTimer.Close();
	}

void CBossScroller::StartL(TInt aOldBlankRow, TInt aOldBlankCol, TInt aNewBlankRow, TInt aNewBlankCol)
	{
	// cancel any existing scroll, just in case - but shouldn't be necessary!
	Cancel();
	// remember parameters
	iOldBlankRow=aOldBlankRow;
	iOldBlankCol=aOldBlankCol;
	iNewBlankRow=aNewBlankRow;
	iNewBlankCol=aNewBlankCol;
	// old and new rectangles
	TRect oldBlankRect;
	iView->GetTileRect(oldBlankRect, aOldBlankRow, aOldBlankCol);
	TRect newBlankRect;
	iView->GetTileRect(newBlankRect, aNewBlankRow, aNewBlankCol);
	// bounding rectangle for scroll action
	iBoundingRect=oldBlankRect;
	iBoundingRect.BoundingRect(newBlankRect);
	// tile scrolls from new-blank to old-blank - get vector between them
	iVectorNeeded=oldBlankRect.iTl-newBlankRect.iTl;
	iScalarNeeded=iVectorNeeded.iX==0 ? iVectorNeeded.iY : iVectorNeeded.iX;
	if (iScalarNeeded < 0)
		iScalarNeeded = -iScalarNeeded;
	iScalarIncrement=iScalarNeeded / KBossScrollIncrements;
	if (iScalarIncrement * KBossScrollIncrements < iScalarNeeded)
		iScalarIncrement+=1;
	// calculate unit vector in direction of scroll
	iUnitVector=TPoint(0,0);
	if (iVectorNeeded.iX > 0) iUnitVector.iX=1;
	if (iVectorNeeded.iX < 0) iUnitVector.iX=-1;
	if (iVectorNeeded.iY > 0) iUnitVector.iY=1;
	if (iVectorNeeded.iY < 0) iUnitVector.iY=-1;
	// nothing done yet
	iScalarDone=0;
	// do first incremental scroll
	DoIncrement();
	}

void CBossScroller::DoIncrement()
	{
	// do first incremental scroll
	iScalarDone+=iScalarIncrement;
	TInt increment=iScalarIncrement;
	if (iScalarDone > iScalarNeeded)
		{
		increment-=iScalarDone-iScalarNeeded;
		iScalarDone=iScalarNeeded;
		}
	// scroll the tile
	iWindow.Scroll(iBoundingRect, increment * iUnitVector);
	// retro-draw the exposed part of the blank, now
	CWindowGc* gc=(CWindowGc*) (iView->iGc);
	gc->Activate(iWindow);
	iWindow.BeginRedraw(iBoundingRect); // clip to invalid region from scroll
	iView->DrawTile(iNewBlankRow, iNewBlankCol);
	iWindow.EndRedraw();
	gc->Deactivate();
	// quit if finished
	if (iScalarDone==iScalarNeeded)
		return;
	// wait for a short while if not
	iTimer.After(iStatus, KBossScrollTime);
	SetActive();
	}

void CBossScroller::DoCancel()
	{
	// stop waiting
	iTimer.Cancel();
	// make sure drawing is in sync
	CWindowGc* gc=(CWindowGc*) (iView->iGc);
	gc->Activate(iWindow);
	iWindow.Invalidate(iBoundingRect); // invalidate old and new tiles
	iWindow.BeginRedraw(iBoundingRect);
	iView->DrawTile(iOldBlankRow, iOldBlankCol); // tile
	iView->DrawTile(iNewBlankRow, iNewBlankCol); // blank
	iWindow.EndRedraw();
	gc->Deactivate();
	}

void CBossScroller::RunL()
	{
	DoIncrement();
	}

// required as a DLL

EXPORT_C TInt E32Dll(TDllReason)
	{
	return 0;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -