// EIKLABEL.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eiklabel.h>
#include <coeutils.h>
#include <eikenv.h>
#include <eikpanic.h>
#include <barsread.h>
#include <eiklabel.hrh>

#include <eikcolor.h>

const TInt KTextEmphasisMask		= 0x30;
const TInt KTextBufferReserveLength = 0x40;

EXPORT_C CEikLabel::~CEikLabel()
	{
	delete(iText);
	}

EXPORT_C CEikLabel::CEikLabel()	: iGapBetweenLines(1) // default
	{
	__DECLARE_NAME(_S("CEikLabel"));
	iFont=iCoeEnv->NormalFont();
	}

EXPORT_C void CEikLabel::ConstructFromResourceL(TResourceReader& aReader)
	{
	iAlignment.SetHAlignment((TCoeHAlignment)aReader.ReadInt16());
	iAlignment.SetVAlignment((TCoeVAlignment)aReader.ReadInt16());
	TInt standardFont=aReader.ReadInt16();
	switch (standardFont)
		{
	case EEikLabelFontLegend:
		iFont=iEikonEnv->LegendFont();
		break;
	case EEikLabelFontAnnotation:
		iFont=iEikonEnv->AnnotationFont();
		break;
	default:
		break;
		}
	TInt length=aReader.ReadInt16();
	if (length)
		SetBufferReserveLengthL(length);
	SetTextL(aReader.ReadTPtrC());
	}
       
EXPORT_C void CEikLabel::SetTextL(const TDesC& aText)
	{
	__ASSERT_DEBUG(&aText,Panic(EEikPanicLabelNullText));
	if (iLabFlags&KTextBufferReserveLength)
        *iText=aText; // will panic if not long enough
    else
        {
        HBufC* newText=aText.AllocL();
	    delete(iText); // after the AllocL succeeds
	    iText=newText;
        }
    iNumberOfLines=1;
    TPtrC ptr=(*iText);
    FOREVER
        {
        const TInt offset=ptr.Locate('\n');
        if (offset<0 || offset==ptr.Length()-1)
            return;
        iNumberOfLines++;
        ptr.Set(ptr.Mid(offset+1));
        }
	}

TInt CEikLabel::HeightInPixels() const
    {
    return(iMargin.iTop+iMargin.iBottom + iGapBetweenLines*(iNumberOfLines-1) + iNumberOfLines*iFont->HeightInPixels());
    }

TInt CEikLabel::WidthInPixels() const
    {
	__ASSERT_ALWAYS(iText,Panic(EEikPanicLabelNullText));
    TInt maxLineWidth=0;
    TPtrC ptr=(*iText);
    FOREVER
        {
        const TInt offset=ptr.Locate('\n');
        TPtrC left=ptr;
        if (offset>=0)
            left.Set(ptr.Left(offset));
        TInt thisWidth=iFont->TextWidthInPixels(left);
        if (thisWidth>maxLineWidth)
            maxLineWidth=thisWidth;
        if (offset<0 || offset==ptr.Length()-1)
            break;
        ptr.Set(ptr.Mid(offset+1));
        }
    return(iMargin.iLeft + iMargin.iRight + maxLineWidth);
    }

EXPORT_C void CEikLabel::Draw(const TRect& /*aRect*/) const
	{
	__ASSERT_ALWAYS(iText,Panic(EEikPanicLabelNullText));
	CWindowGc& gc = SystemGc();
	if ((iLabFlags&KTextEmphasisMask) != ENoEmphasis)
		SetupGcForEmphasis(gc);
	else if (IsDimmed())
		gc.SetPenColor(iEikonEnv->ControlColor(EEikColorLabelDimmedText,*this));
    gc.UseFont(iFont);
	const TRect rect = Rect();
    const TInt deltaHeight=rect.Height()-HeightInPixels();
    TInt preHeight=iMargin.iTop; // used on first line
    TInt postHeight=iMargin.iBottom; // used on last line
    if (deltaHeight>0)
        {
        switch(iAlignment.VAlignment())
            {
		case EVTop:
            postHeight+=deltaHeight;
            break;
		case EVBottom:
            preHeight+=deltaHeight;
            break;
        case EVCenter:
            TInt postInc=deltaHeight/2; // give odd pixel to pre-Height
            preHeight+=deltaHeight-postInc;
            postHeight+=postInc;
            }
        }
    TInt lineNo=0;
    TPtrC ptr=(*iText);
    TRect box=rect;
    TBool clippedAtBottom=EFalse;
    FOREVER
        {
        TInt ascent=iFont->AscentInPixels()+preHeight;
        TInt lineHeight=iFont->HeightInPixels()+preHeight;
        if (++lineNo==iNumberOfLines)
            lineHeight+=postHeight;
        TInt off=ptr.Locate('\n');
        TPtrC left=ptr;
        if (off>=0)
            left.Set(ptr.Left(off));
        box.iBr.iY=box.iTl.iY+lineHeight;
        if (box.iBr.iY>rect.iBr.iY)
            {
            box.iBr.iY=rect.iBr.iY;
            clippedAtBottom=ETrue;
            }
        CGraphicsContext::TTextAlign align=iAlignment.TextAlign();
		TInt margin = iMargin.iLeft;
		if (align==CGraphicsContext::ERight)
			margin = iMargin.iRight;
		else if (align==CGraphicsContext::ECenter)
			margin -= iMargin.iRight;
		EikDrawUtils::DrawText(gc,left,box,ascent,align,margin,iFont);
        if (off<0 || off==ptr.Length()-1 || clippedAtBottom)
            break;
        ptr.Set(ptr.Mid(off+1));
        box.iTl.iY=box.iBr.iY;
        preHeight=iGapBetweenLines;
        }
	}

EXPORT_C void CEikLabel::SetBufferReserveLengthL(TInt aLength)
	{
	if (iText)
		iText=iText->ReAllocL(aLength);
	else
		iText=HBufC::NewL(aLength);
	iLabFlags|=KTextBufferReserveLength;
	}

EXPORT_C void CEikLabel::SetFont(const CFont* aFont) 
	{
	iFont=aFont;
	}

EXPORT_C void CEikLabel::SetEmphasis(TTextEmphasis aEmphasis)
	{
    iLabFlags&=(~KTextEmphasisMask);
    iLabFlags|=aEmphasis;
	}

EXPORT_C TSize CEikLabel::MinimumSize()
	{
	iSize=TSize(WidthInPixels(),HeightInPixels());
	return(iSize);
	}

EXPORT_C void CEikLabel::SetPixelGapBetweenLines(TInt aGap)
	{
	iGapBetweenLines=aGap;
	}

EXPORT_C TInt CEikLabel::PixelGapBetweenLines() const
	{
	return iGapBetweenLines;
	}

void CEikLabel::SetupGcForEmphasis(CGraphicsContext& aGc) const
	{
	aGc.SetPenColor(iEikonEnv->ControlColor(EEikColorLabelTextEmphasis,*this));
	aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
	if ((iLabFlags&KTextEmphasisMask) == EFullEmphasis)
		aGc.SetBrushColor(iEikonEnv->ControlColor(EEikColorLabelHighlightFullEmphasis,*this));
	else
		aGc.SetBrushColor(iEikonEnv->ControlColor(EEikColorLabelHighlightPartialEmphasis,*this));
	}

EXPORT_C void CEikLabel::Reserved_1()
	{}
EXPORT_C void CEikLabel::Reserved_2()
	{}
