// EIKFONTD.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikfontd.h>
#include <coemain.h>
#include <badesca.h>
#include <eikpriv.hrh>
#include <eikfntut.h>
#include <eikchkbx.h>
#include <eikchlst.h>
#include <eikfprev.h>
#include <eikenv.h>
#include <eikchlst.hrh>
#include <eikftflg.hrh>

enum {EGranularity=4}; 

EXPORT_C CEikFontDialog::CEikFontDialog(TCharFormat& aFormat,TCharFormatMask& aAttribChangedMask,
										TInt aFontDialogFlags,CGraphicsDevice* aGraphicsDevice,
										TInt aFontControlFlags,const TRgb aBackGroundColor)
	: iFontFlags(aFontDialogFlags),
	iFontControlFlags(aFontControlFlags),
	iGraphicsDevice(aGraphicsDevice),
	iActiveFormat(&aFormat),
	iAttribChangedMask(&aAttribChangedMask),
	iBackGroundColor(aBackGroundColor)
	{
	}

EXPORT_C CEikFontDialog::CEikFontDialog(TCharFormat& aFormat,TCharFormatMask& aAttribChangedMask,
										TCharFormatMask& aUndeterminedMask,TDesC& aTextSelection,
										TInt aFontDialogFlags,CGraphicsDevice* aGraphicsDevice,
										TInt aFontControlFlags,const TRgb aBackGroundColor)
	: iFontFlags(aFontDialogFlags),
	iFontControlFlags(aFontControlFlags),
	iGraphicsDevice(aGraphicsDevice),
	iActiveFormat(&aFormat),
	iAttribChangedMask(&aAttribChangedMask),
	iUndeterminedMask(aUndeterminedMask),
	iTextSelection(aTextSelection),
	iBackGroundColor(aBackGroundColor)
	{
	}
									     
void CEikFontDialog::ConstructArraysL()
	{
	iFontNameList=new(ELeave) CDesCArrayFlat(EGranularity);
	iFontHeightList=new(ELeave) CDesCArrayFlat(EGranularity);
	iTwipsList=new(ELeave) CArrayFixFlat<TInt>(EGranularity);
	}
										
EXPORT_C CEikFontDialog::~CEikFontDialog()
	{
	delete(iFontNameList);
	delete(iTwipsList);
	delete(iFontHeightList);
	if (iPreviewFont)
		iCoeEnv->ReleaseScreenFont(iPreviewFont);
	} 

void CEikFontDialog::UpdateHeightListL()
	{
	const TInt index=ChoiceListCurrentItem(EEikCidFontNameList);
	if (index==-1)
		return;
	EikFontUtils::GetAvailableHeightsInTwipsAndPointsL(*iGraphicsDevice,(*iFontNameList)[index],*iTwipsList,*iFontHeightList);
	iHeightInTwips=iActiveFormat->iFontSpec.iHeight;
	CEikChoiceList* sizeList=(CEikChoiceList*)Control(EEikCidFontSizeList);
	sizeList->SetArrayL(iFontHeightList);
	const TInt pos=EikFontUtils::IndexOfNearestHeight(*iTwipsList,iHeightInTwips);
	SetChoiceListCurrentItem(EEikCidFontSizeList,pos);
	}

void CEikFontDialog::BuildFontNameListL()
    {
	EikFontUtils::GetAvailableFontsL(*iGraphicsDevice,*iFontNameList,iFontFlags);
	CEikChoiceList* nameList=(CEikChoiceList*)Control(EEikCidFontNameList);
	nameList->SetArrayL(iFontNameList);
	//if (fontname is not in the list,get the nearest font.)
	TInt pos=0;	 //find returns nonzero if not found
	if (iFontNameList->Find(iActiveFormat->iFontSpec.iTypeface.iName,pos))
		{
		CFont* font;
		User::LeaveIfError(iGraphicsDevice->GetNearestFontInTwips(font,iActiveFormat->iFontSpec));
		iActiveFormat->iFontSpec=font->FontSpecInTwips();
		iActiveFormat->iFontSpec.iTypeface.SetAttributes(EikFontUtils::TypefaceAttributes(*iGraphicsDevice,iActiveFormat->iFontSpec.iTypeface.iName));
		iAttribChangedMask->SetAttrib(EAttFontTypeface);	 
		iAttribChangedMask->SetAttrib(EAttFontHeight);	 
		iGraphicsDevice->ReleaseFont(font);
		}
    }

void CEikFontDialog::PreLayoutDynInitL()  // Called when the dialog is loaded
	{
    ConstructArraysL();
	if (!iGraphicsDevice)
		iGraphicsDevice=iCoeEnv->ScreenDevice();

	CEikButtonBase::TState button=CEikButtonBase::EClear;
	//underline
	if (iUndeterminedMask.AttribIsSet(EAttFontUnderline))
		button=CEikButtonBase::EIndeterminate;		
	else if (iActiveFormat->iFontPresentation.iUnderline==EUnderlineOn)
		button=CEikButtonBase::ESet;
	((CEikCheckBox*)Control(EEikCidFontUnderlineTkBx))->SetState(button);
	//strikethrough
	button=CEikButtonBase::EClear;
	if (iUndeterminedMask.AttribIsSet(EAttFontStrikethrough))
		button=CEikButtonBase::EIndeterminate;		
	else if (iActiveFormat->iFontPresentation.iStrikethrough==EStrikethroughOn)
		button=CEikButtonBase::ESet;
	((CEikCheckBox*)Control(EEikCidFontStrikethruTkBx))->SetState(button);
	//bold
	button=CEikButtonBase::EClear;
	if (iUndeterminedMask.AttribIsSet(EAttFontStrokeWeight))	//strokeweight
		button=CEikButtonBase::EIndeterminate;		
	else if (iActiveFormat->iFontSpec.iFontStyle.StrokeWeight()==EStrokeWeightBold)
		button=CEikButtonBase::ESet;
	((CEikCheckBox*)Control(EEikCidFontBoldTkBx))->SetState(button);
	 //italic
	button=CEikButtonBase::EClear;
	if (iUndeterminedMask.AttribIsSet(EAttFontPosture))	//posture
		button=CEikButtonBase::EIndeterminate;		
	else if (iActiveFormat->iFontSpec.iFontStyle.Posture()==EPostureItalic)
		button=CEikButtonBase::ESet;
	((CEikCheckBox*)Control(EEikCidFontItalicTkBx))->SetState(button);
	//printpos
  TInt focusItem=0;
	if (!iUndeterminedMask.AttribIsSet(EAttFontPrintPos))
		{
		if (iActiveFormat->iFontSpec.iFontStyle.PrintPosition()==EPrintPosSuperscript)	
			focusItem=1;
		else if (iActiveFormat->iFontSpec.iFontStyle.PrintPosition()==EPrintPosSubscript)	
			focusItem=2;
		}
	else
		focusItem=-1;
	SetChoiceListCurrentItem(EEikCidFontPrintPosList,focusItem);
	//text color
	SetGraySelectorColor(EEikCidTextColor,iActiveFormat->iFontPresentation.iTextColor);

	// Font names
    BuildFontNameListL();
	TInt pos=0;
	if (iUndeterminedMask.AttribIsSet(EAttFontTypeface))
		pos=-1;
	else
		{
		if (iFontNameList->Find(iActiveFormat->iFontSpec.iTypeface.iName,pos))
            pos=0;
		}
	SetChoiceListCurrentItem(EEikCidFontNameList,pos);

	//heights  
	UpdateHeightListL();
	if (iUndeterminedMask.AttribIsSet(EAttFontHeight))
		{
		pos=-1;
		SetChoiceListCurrentItem(EEikCidFontSizeList,pos);
		}
	SetFontPreviewL();
	}

void CEikFontDialog::PostLayoutDynInitL()
	{
	if (iFontControlFlags&EEikFontControlAll)
		return;
	if (iFontControlFlags&EEikFontControlBold)
		MakeLineVisible(EEikCidFontBoldTkBx,EFalse);

	if (iFontControlFlags&EEikFontControlItalic)
		MakeLineVisible(EEikCidFontItalicTkBx,EFalse);
	
	if (iFontControlFlags&EEikFontControlUnderline)
		MakeLineVisible(EEikCidFontUnderlineTkBx,EFalse);
	
	if (iFontControlFlags&EEikFontControlStrikethrough)
		MakeLineVisible(EEikCidFontStrikethruTkBx,EFalse);
	
	if (iFontControlFlags&EEikFontControlPrintPos)
		MakeLineVisible(EEikCidFontPrintPosList,EFalse);
	
	if (iFontControlFlags&EEikFontControlTextColor)
		MakeLineVisible(EEikCidTextColor,EFalse);
	}

void CEikFontDialog::HandleControlStateChangeL(TInt aControlId)  
	{
	TInt index=0;
	CEikButtonBase::TState button=CEikButtonBase::EClear;
	switch(aControlId)
		{
	case EEikCidFontNameList:
		{
		UpdateHeightListL();
		index=ChoiceListCurrentItem(EEikCidFontNameList);
		if (index==-1)
			break;
		iAttribChangedMask->SetAttrib(EAttFontTypeface);	 
		iActiveFormat->iFontSpec.iTypeface.iName=(*iFontNameList)[index];
		iActiveFormat->iFontSpec.iTypeface.SetAttributes(EikFontUtils::TypefaceAttributes(*iGraphicsDevice,iActiveFormat->iFontSpec.iTypeface.iName));
		}

		//break;	   intentional drop through code because height has been altered
	case EEikCidFontSizeList:
		index=ChoiceListCurrentItem(EEikCidFontSizeList);
		iAttribChangedMask->SetAttrib(EAttFontHeight);	
		iActiveFormat->iFontSpec.iHeight=(*iTwipsList)[index];
		break;
	case EEikCidFontItalicTkBx:
		{
		button=((CEikCheckBox*)Control(EEikCidFontItalicTkBx))->State();
		iAttribChangedMask->SetAttrib(EAttFontPosture);
		TFontPosture posture=(button==CEikButtonBase::ESet?EPostureItalic:EPostureUpright);
		iActiveFormat->iFontSpec.iFontStyle.SetPosture(posture);
		break;
		}
	case EEikCidFontBoldTkBx:
		{
		button=((CEikCheckBox*)Control(EEikCidFontBoldTkBx))->State();
		iAttribChangedMask->SetAttrib(EAttFontStrokeWeight);
		TFontStrokeWeight weight=(button&CEikButtonBase::ESet?EStrokeWeightBold:EStrokeWeightNormal);
		iActiveFormat->iFontSpec.iFontStyle.SetStrokeWeight(weight);
		break;
		}
	case EEikCidFontPrintPosList:
		{
		TInt index=((CEikChoiceList*)Control(EEikCidFontPrintPosList))->CurrentItem();
		TFontPrintPosition fontPrintPosition=EPrintPosNormal;
		switch (index)
			{
		case 0:
			fontPrintPosition=EPrintPosNormal;
			break;
		case 1:
			fontPrintPosition=EPrintPosSuperscript;
			break;
		case 2:
			fontPrintPosition=EPrintPosSubscript;
			break;
		default:
			;
			}
		iAttribChangedMask->SetAttrib(EAttFontPrintPos);
		iActiveFormat->iFontSpec.iFontStyle.SetPrintPosition(fontPrintPosition);
		}
		break;
	case EEikCidTextColor:
		{
		const TRgb color=GraySelectorColor(EEikCidTextColor);
		iAttribChangedMask->SetAttrib(EAttColor);	 
		iActiveFormat->iFontPresentation.iTextColor=color;
		break;
		}
	case EEikCidFontUnderlineTkBx:
		button=((CEikCheckBox*)Control(EEikCidFontUnderlineTkBx))->State();
		iAttribChangedMask->SetAttrib(EAttFontUnderline);
		iActiveFormat->iFontPresentation.iUnderline=(button&CEikButtonBase::ESet?EUnderlineOn:EUnderlineOff); //True:EFalse);
		break;
	case EEikCidFontStrikethruTkBx:
		button=((CEikCheckBox*)Control(EEikCidFontStrikethruTkBx))->State();
		iAttribChangedMask->SetAttrib(EAttFontStrikethrough);
		iActiveFormat->iFontPresentation.iStrikethrough=(button&CEikButtonBase::ESet?EStrikethroughOn:EStrikethroughOff); 
		break;
		}
	DoFontPreviewL();
	}

void CEikFontDialog::SetFontPreviewL()
	{
	TBool notext=EFalse;
	if (ChoiceListCurrentItem(EEikCidFontNameList)==-1)
		notext=ETrue;
	CFbsFont* font=iCoeEnv->CreateScreenFontL(iActiveFormat->iFontSpec);
	if (iPreviewFont)
		iCoeEnv->ReleaseScreenFont(iPreviewFont);
	iPreviewFont=font;
	TBuf<KTextSelectionMaxLen> previewBuf;
	if (iTextSelection.Length())
		previewBuf.Append(iTextSelection);
	else
		{
		TInt index=ChoiceListCurrentItem(EEikCidFontNameList);
		if (index==-1)
			index=0;
		previewBuf.Append((*iFontNameList)[index]); 
		}
	CEikFontPreviewLabel* label1=((CEikFontPreviewLabel*)Control(EEikCidFontPreviewLabelOne));
	label1->SetFont(font);
	label1->SetUnderline(iActiveFormat->iFontPresentation.iUnderline?EUnderlineOn:EUnderlineOff);
	label1->SetStrikethrough(iActiveFormat->iFontPresentation.iStrikethrough?EStrikethroughOn:EStrikethroughOff);
	if (notext)
		label1->SetPenColor(iBackGroundColor);
	else
		label1->SetPenColor(iActiveFormat->iFontPresentation.iTextColor);
	label1->SetTextL(previewBuf);
	label1->SetBackgroundColor(iBackGroundColor);

	//preview on second page
	CEikFontPreviewLabel* label2=((CEikFontPreviewLabel*)Control(EEikCidFontPreviewLabelTwo));
	label2->SetFont(font);
	label2->SetUnderline(iActiveFormat->iFontPresentation.iUnderline?EUnderlineOn:EUnderlineOff);
	label2->SetStrikethrough(iActiveFormat->iFontPresentation.iStrikethrough?EStrikethroughOn:EStrikethroughOff);
	if (notext)
		label1->SetPenColor(iBackGroundColor);
	else
		label2->SetPenColor(iActiveFormat->iFontPresentation.iTextColor);
	label2->SetTextL(previewBuf);
	label2->SetBackgroundColor(iBackGroundColor);
	}

void CEikFontDialog::DoFontPreviewL()
	{
	SetFontPreviewL();
	Control(EEikCidFontPreviewLabelOne)->DrawNow();
	Control(EEikCidFontPreviewLabelTwo)->DrawNow();
	}
