// TSCRLB0.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikenv.h>
#include <coecntrl.h>
#include <eikappui.h>
#include <eikdef.h>
#include <eikscrlb.h>
#include <eikdialg.h>
#include <eikmenup.h>
#include <eikmenu.hrh>
#include <coecobs.h>
#include <basched.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <tscrlb0.rsg>
#include "tscrlb0.hrh"

//
// class CSimpleDialog
//

class CSimpleDialog : public CEikDialog
	{
public:
	CSimpleDialog(TPoint* aInfo) : iInfo(aInfo) {}
private: // virtual
    virtual TBool OkToExitL(TInt aKeyCode);
    virtual void PreLayoutDynInitL();
private:
	TPoint* iInfo;
	};

TBool CSimpleDialog::OkToExitL(TInt /* aKeyCode*/)
	{
	iInfo->iX=(ChoiceListCurrentItem(EDlgChlstHoriz)+1)*5;
	iInfo->iY=(ChoiceListCurrentItem(EDlgChlstVert)+1)*5;
	return ETrue;
	}

void CSimpleDialog::PreLayoutDynInitL()
	{
	SetChoiceListCurrentItem(EDlgChlstHoriz, (iInfo->iX/5)-1);
	SetChoiceListCurrentItem(EDlgChlstVert, (iInfo->iY/5)-1);
	}

//
// class TBitmapInfo
//

class TBitmapInfo
	{
public:
	TBitmapInfo() {}
	TBitmapInfo(TInt aXProportion, TInt aXPosition, TInt aYProportion, TInt aYPosition)
		: iXProportion(aXProportion), iXPosition(aXPosition), iYProportion(aYProportion), iYPosition(aYPosition)
		{}
	void CheckPositions();
public:
	TInt iXProportion;
	TInt iXPosition;
	TInt iYProportion;
	TInt iYPosition;
	};

void TBitmapInfo::CheckPositions()
	{
	iXPosition=Max(0, Min(iXPosition, 100-iXProportion));
	iYPosition=Max(0, Min(iYPosition, 100-iYProportion));
	}

//
// class CBitmapControl
//

class CBitmapControl : public CCoeControl
	{
public:
	CBitmapControl() {}
	~CBitmapControl();
	void ConstructL(const TDesC& aFileName, const TBitmapInfo& aBitmapInfo);
	TSize MinimumSize() const;
	TSize MaximumSize() const;
	void SetBitmapInfoL(const TBitmapInfo& aBitmapInfo);
	const TBitmapInfo* BitmapInfo() const { return &iBitmapInfo; }
private:
	void Draw(const TRect& aRect) const;
private:
	TBitmapInfo iBitmapInfo;
	CFbsBitmap* iBitmap;
	};

CBitmapControl::~CBitmapControl()
	{
	delete iBitmap;
	}

void CBitmapControl::ConstructL(const TDesC& aFileName, const TBitmapInfo& aBitmapInfo)
	{
	iBitmapInfo=aBitmapInfo;
	iBitmap=iEikonEnv->CreateBitmapL(aFileName, 0);
	}

TSize CBitmapControl::MinimumSize() const
	{
	TSize bitmapSize=iBitmap->SizeInPixels();
	return TSize(bitmapSize.iWidth*iBitmapInfo.iXProportion/100, bitmapSize.iHeight*iBitmapInfo.iYProportion/100);
	}

TSize CBitmapControl::MaximumSize() const
	{
	return iBitmap->SizeInPixels();
	}

void CBitmapControl::SetBitmapInfoL(const TBitmapInfo& aBitmapInfo)
	{
	TBitmapInfo oldBitmapInfo=iBitmapInfo;
	iBitmapInfo=aBitmapInfo;
	if ((oldBitmapInfo.iXProportion!=iBitmapInfo.iXProportion)||(oldBitmapInfo.iYProportion!=iBitmapInfo.iYProportion))
		SetSizeL(MinimumSize());
	}

void CBitmapControl::Draw(const TRect& /*aRect*/) const
	{
	CWindowGc& gc=SystemGc();
	TSize bitmapSize(iBitmap->SizeInPixels());
	TPoint bitmapTopLeft(bitmapSize.iWidth*iBitmapInfo.iXPosition/100, bitmapSize.iHeight*iBitmapInfo.iYPosition/100);
	TSize bitmapVisibleSize(bitmapSize.iWidth*iBitmapInfo.iXProportion/100, bitmapSize.iHeight*iBitmapInfo.iYProportion/100);
	TRect visibleRect(bitmapTopLeft, bitmapVisibleSize);
	gc.BitBlt(iPosition, iBitmap, visibleRect);
	}

//
// TEikScrollBarInfo
//

class TEikScrollBarInfo
	{
	
public:
	TBool operator==(const TEikScrollBarInfo& aInfo) const;
public:
	TBool iNudge;
	TBool iPage;
	TBool iHomeEnd;
	TBool iAutoDim;
	};

TBool TEikScrollBarInfo::operator==(const TEikScrollBarInfo& aInfo)	const
	{
	return((aInfo.iNudge==iNudge)&(aInfo.iPage==iPage)&(aInfo.iHomeEnd==iHomeEnd)&(aInfo.iAutoDim==iAutoDim));
	}

//
// class CTestContainer
//

class CTestContainer : public CCoeControl, public MEikScrollBarObserver
    {
public:
    void ConstructL();
    ~CTestContainer();
    void HandleCommandL(TInt aCommand);
	void DynInitMenuPaneL(TInt aMenuId,CEikMenuPane* aMenuPane);
private: // framework
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
    void Draw(const TRect& aRect) const;
    TInt CountComponentControls() const;
    CCoeControl* ComponentControl(TInt aIndex) const;
private: // from MEikScrollBarObserver
	void HandleScrollEventL(CEikScrollBar* aScrollBar, TEikScrollEvent aEvent);
private: // new functions
	void CreateComponentControlsL();
	void CreateScrollBarL(CEikScrollBar::TOrientation aOrienation);
private:
	TBitmapInfo iBitmapInfo;
	TEikScrollBarInfo iHInfo;
	TEikScrollBarInfo iVInfo;
	CBitmapControl* iBitmapControl;	// lodger component
	CEikScrollBar* iHBar;			// owns window
	CEikScrollBar* iVBar;			// owns window
	TBool iHDimmed;
	TBool iVDimmed;
    };

void CTestContainer::ConstructL()
    {
    CreateWindowL();
    Window().SetShadowDisabled(ETrue);
    EnableDragEvents();
    CreateComponentControlsL();
    SetExtentToWholeScreenL();
    ActivateL();
    }

CTestContainer::~CTestContainer()
    {
	delete iBitmapControl;
	delete iHBar;
	delete iVBar;
    }

TKeyResponse CTestContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    if (aType!=EEventKey)
        return(EKeyWasNotConsumed);
    TInt code=aKeyEvent.iCode;
    if (code==CTRL('e'))
        CBaActiveScheduler::Exit();
	return(EKeyWasConsumed);
    }

void CTestContainer::CreateComponentControlsL()
    {
	iBitmapControl=new(ELeave) CBitmapControl;
	TPtrC fileName=_L("z:\\System\\Test\\jurass2.mbm");
	iBitmapInfo=TBitmapInfo(90,0,40,0);
	iBitmapControl->ConstructL(fileName, iBitmapInfo);
	iBitmapControl->SetContainerWindowL(*this);
	TSize bitmapSize=iBitmapControl->MinimumSize();
	TSize maxBitmapSize=iBitmapControl->MaximumSize();
	iBitmapControl->SetExtentL(TPoint((580-maxBitmapSize.iWidth),(240-maxBitmapSize.iHeight)/2), bitmapSize);
	iBitmapControl->ActivateL();
	iHInfo.iNudge=iVInfo.iNudge=ETrue;
	iHInfo.iAutoDim=iVInfo.iAutoDim=ETrue;
	CreateScrollBarL(CEikScrollBar::EHorizontal);
	CreateScrollBarL(CEikScrollBar::EVertical);
	iEikonEnv->InfoMsg(R_TSB0_INFO_MSG);
    }

void CTestContainer::CreateScrollBarL(CEikScrollBar::TOrientation aOrientation)
	{
	TPoint pos=iCoeEnv->ScreenDevice()->SizeInPixels().AsPoint();
	pos.iX-=CEikScrollBar::EScrollbarWidth;
	pos.iY-=CEikScrollBar::EScrollbarWidth;
	TBool horiz=(aOrientation==CEikScrollBar::EHorizontal);
	CEikScrollBar*& bar=(horiz)? iHBar : iVBar;
	TEikScrollBarInfo& info=(horiz)? iHInfo : iVInfo;
	TInt length=(horiz)? pos.iX : pos.iY;
	if (horiz)
		pos.iX=0;
	else
		pos.iY=0;
	TInt proportion=(horiz)? iBitmapInfo.iXProportion : iBitmapInfo.iYProportion;
	TInt position=(horiz)? iBitmapInfo.iXPosition : iBitmapInfo.iYPosition;
	TEikScrollBarModel model(100, proportion, position);
	TInt flags=0;
	if (!info.iNudge)
		flags|=CEikScrollBar::EEikScrollBarNoNudgeButtons;
	if (info.iPage)
		flags|=CEikScrollBar::EEikScrollBarHasPageButtons;
	if (info.iHomeEnd)
		flags|=CEikScrollBar::EEikScrollBarHasHomeEndButtons;
	if (!info.iAutoDim)
		flags|=CEikScrollBar::ENoAutoDimming;
	bar=new(ELeave) CEikScrollBar;
	bar->ConstructL(this, this, aOrientation, 0, flags);
	bar->SetPosition(pos);
	bar->SetLengthAndModelL(length, &model);
	bar->ActivateL();
	}

void CTestContainer::HandleScrollEventL(CEikScrollBar* aScrollBar, TEikScrollEvent aEvent)
	{
	TEikScrollBarModel model=*(aScrollBar->Model());
	switch (aEvent)
		{
	default:
		break;
	case EEikScrollEnd:
	case EEikScrollBottom:
		model.iThumbPosition=model.MaxThumbPos();
		break;
	case EEikScrollHome:
	case EEikScrollTop:
		model.iThumbPosition=0;
		break;
	case EEikScrollPageRight:
	case EEikScrollPageDown:
		model.iThumbPosition+=model.iThumbSpan;
		break;
	case EEikScrollPageLeft:
	case EEikScrollPageUp:
		model.iThumbPosition-=model.iThumbSpan;
		break;
	case EEikScrollRight:
	case EEikScrollDown:
		model.iThumbPosition+=Max(1,(model.MaxThumbPos()/20));
		break;
	case EEikScrollLeft:
	case EEikScrollUp:
		model.iThumbPosition-=Max(1,(model.MaxThumbPos()/20));
		}
	model.CheckBounds();
	if (aEvent!=EEikScrollThumbDragHoriz&&aEvent!=EEikScrollThumbDragVert)
		aScrollBar->SetModelThumbPosition(model.iThumbPosition);
	TInt& position=(aEvent&KEikScrollEventBarMask==KEikScrollEventFromHBar)? iBitmapInfo.iXPosition : iBitmapInfo.iYPosition;
	position=model.iThumbPosition;
	iBitmapControl->SetBitmapInfoL(iBitmapInfo);
	iBitmapControl->DrawNow();
	}

TInt CTestContainer::CountComponentControls() const
    {
    return(1);
    }

CCoeControl* CTestContainer::ComponentControl(TInt /*aIndex*/) const
    {
    return(iBitmapControl);
    }

void CTestContainer::Draw(const TRect& /*aRect*/) const
    {
    iEikonEnv->FillTexturedRect(Rect());
    }

void CTestContainer::HandleCommandL(TInt aCommand)
	{
	TEikScrollBarInfo oldHInfo=iHInfo;
	TEikScrollBarInfo oldVInfo=iVInfo;
	TPoint oldProportionInfo(iBitmapInfo.iXProportion, iBitmapInfo.iYProportion);
	TPoint proportionInfo(oldProportionInfo);
	switch (aCommand)
		{
	case EMenuPictureProportion:
		{
		CSimpleDialog* dialog=new(ELeave) CSimpleDialog(&proportionInfo);
		dialog->ExecuteLD(R_TSB0_DIALOG_PICTURE);
		}
		break;
	case EMenuHNudgeButtons:
		iHInfo.iNudge=!iHInfo.iNudge;
		break;
	case EMenuHPageButtons:
		iHInfo.iPage=!iHInfo.iPage;
		break;
	case EMenuHHomeEndButtons:
		iHInfo.iHomeEnd=!iHInfo.iHomeEnd;
		break;
	case EMenuHAutoDimming:
		iHInfo.iAutoDim=!iHInfo.iAutoDim;
		break;
	case EMenuHDimmed:
		iHDimmed=!iHDimmed;
		iHBar->SetDimmed(iHDimmed);
		iHBar->DrawNow();
		break;
	case EMenuVNudgeButtons:
		iVInfo.iNudge=!iVInfo.iNudge;
		break;
	case EMenuVPageButtons:
		iVInfo.iPage=!iVInfo.iPage;
		break;
	case EMenuVHomeEndButtons:
		iVInfo.iHomeEnd=!iVInfo.iHomeEnd;
		break;
	case EMenuVAutoDimming:
		iVInfo.iAutoDim=!iVInfo.iAutoDim;
		break;
	case EMenuVDimmed:
		iVDimmed=!iVDimmed;
		iVBar->SetDimmed(iVDimmed);
		iVBar->DrawNow();
		break;
	default:
		break;
		}
	if (!(oldHInfo==iHInfo))
		{
		delete iHBar;
		CreateScrollBarL(CEikScrollBar::EHorizontal);
		}
	else if (!(oldVInfo==iVInfo))
		{
		delete iVBar;
		CreateScrollBarL(CEikScrollBar::EVertical);
		}
	else if (oldProportionInfo!=proportionInfo)
		{
		iBitmapInfo.iXProportion=proportionInfo.iX;
		iBitmapInfo.iYProportion=proportionInfo.iY;
		iBitmapInfo.CheckPositions();
		iBitmapControl->SetBitmapInfoL(iBitmapInfo);
		DrawNow();
		TEikScrollBarModel hModel(100, iBitmapInfo.iXProportion, iBitmapInfo.iXPosition);
		TEikScrollBarModel vModel(100, iBitmapInfo.iYProportion, iBitmapInfo.iYPosition);
		iHBar->SetModelL(&hModel);
		iVBar->SetModelL(&vModel);
		}
	}

void CTestContainer::DynInitMenuPaneL(TInt aMenuId,CEikMenuPane* aMenuPane)
	{
	switch (aMenuId)
		{
	case R_TSB0_HBAR_MENU:
		if (iHInfo.iNudge)
			aMenuPane->SetItemButtonState(EMenuHNudgeButtons,EEikMenuItemSymbolOn);
		if (iHInfo.iPage)
			aMenuPane->SetItemButtonState(EMenuHPageButtons,EEikMenuItemSymbolOn);
		if (iHInfo.iHomeEnd)
			aMenuPane->SetItemButtonState(EMenuHHomeEndButtons,EEikMenuItemSymbolOn);
		if (iHInfo.iAutoDim)
			aMenuPane->SetItemButtonState(EMenuHAutoDimming,EEikMenuItemSymbolOn);
		if (iHDimmed)
			aMenuPane->SetItemButtonState(EMenuHDimmed,EEikMenuItemSymbolOn);
		break;
	case R_TSB0_VBAR_MENU:
		if (iVInfo.iNudge)
			aMenuPane->SetItemButtonState(EMenuVNudgeButtons,EEikMenuItemSymbolOn);
		if (iVInfo.iPage)
			aMenuPane->SetItemButtonState(EMenuVPageButtons,EEikMenuItemSymbolOn);
		if (iVInfo.iHomeEnd)
			aMenuPane->SetItemButtonState(EMenuVHomeEndButtons,EEikMenuItemSymbolOn);
		if (iVInfo.iAutoDim)
			aMenuPane->SetItemButtonState(EMenuVAutoDimming,EEikMenuItemSymbolOn);
		if (iVDimmed)
			aMenuPane->SetItemButtonState(EMenuVDimmed,EEikMenuItemSymbolOn);
		break;
		}
	}

//
// CSimpleAppUi
//

class CSimpleAppUi : public CEikAppUi
    {
public:
    ~CSimpleAppUi();
    void ConstructL();
private: // framework
    void HandleCommandL(TInt aCommand);
	void DynInitMenuPaneL(TInt aMenuId,CEikMenuPane* aMenuPane);
private:
    CTestContainer* iContainer;
    };

CSimpleAppUi::~CSimpleAppUi()
    {
    delete(iContainer);
    }
    
void CSimpleAppUi::ConstructL()
    {
    BaseConstructL(/*ENonStandardResourceFile*/);
    iContainer=new(ELeave) CTestContainer;
    iContainer->ConstructL();
    AddToStackL(iContainer);
    }

void CSimpleAppUi::DynInitMenuPaneL(TInt aMenuId,CEikMenuPane* aMenuPane)
	{
	iContainer->DynInitMenuPaneL(aMenuId, aMenuPane);
    }						

void CSimpleAppUi::HandleCommandL(TInt aCommand)
	{
	switch (aCommand)
		{
	case EMenuCommandExit:
		CBaActiveScheduler::Exit();
	default:
		iContainer->HandleCommandL(aCommand);
		}
	}

//
// CSimpleDocument
//

class CSimpleDocument : public CEikDocument
	{
public:
	CSimpleDocument(CEikApplication& aApp): CEikDocument(aApp) { }
private: // from CApaDocument
	CEikAppUi* CreateAppUiL();
	};

CEikAppUi* CSimpleDocument::CreateAppUiL()
	{
    return(new(ELeave) CSimpleAppUi);
	}

//
// CSimpleApplication
//

class CSimpleApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

const TUid KUidSimpleApp={217};

TUid CSimpleApplication::AppDllUid() const
	{
	return(KUidSimpleApp);
	}

CApaDocument* CSimpleApplication::CreateDocumentL()
	{
	return(new(ELeave) CSimpleDocument(*this));
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CSimpleApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
