// EIKBUTB.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikbutb.h>
#include <coemain.h>

const TInt KButtonStateMask             =0x000f;
const TInt KButtonPressedMask           =0x0010;
const TInt KButtonDrawStateMask         =0x001f;
const TInt KButtonReportOnPointerDown	=0x0020;
const TInt KButtonTristate	            =0x0040;
const TInt KButtonAllowTristate	        =0x0080;
const TInt KButtonBehaviorMask			=0x0f00;

const TInt KAnimationDelayInMicroSeconds=50000;

EXPORT_C CEikButtonBase::~CEikButtonBase()
    {}

EXPORT_C CEikButtonBase::CEikButtonBase()
    {
	__DECLARE_NAME(_S("CEikButtonBase"));
    }

EXPORT_C void CEikButtonBase::SetCoordinator(TEikButtonCoordinator* aButCoord)
	{
	iButCoord=aButCoord;
	}

EXPORT_C CEikButtonBase::TState CEikButtonBase::State() const
    {
    return((TState)(iButFlags&KButtonStateMask));
    }

EXPORT_C void CEikButtonBase::SetState(TState aState)
    {
    iButFlags&=(~KButtonStateMask);
    iButFlags|=aState;
    if (aState==EIndeterminate && iButFlags&KButtonAllowTristate)
        iButFlags|=KButtonTristate;
	if (aState==ESet && iButCoord)
		iButCoord->SetChosenButton(this);
    StateChanged();
    }

EXPORT_C void CEikButtonBase::StateChanged()
	{
	}

EXPORT_C TBool CEikButtonBase::IsPressed() const
    {
    return(iButFlags&KButtonPressedMask);
    }

EXPORT_C CEikButtonBase::TDrawState CEikButtonBase::DrawState() const
    {
    return((TDrawState)(iButFlags&KButtonDrawStateMask));
    }

EXPORT_C void CEikButtonBase::CopyDrawStateTo(CEikButtonBase* aTargetButton) const
    { // intended to be called from inside the StateChanged() function of a container button
    aTargetButton->iButFlags&=(~KButtonDrawStateMask);
    aTargetButton->iButFlags|=DrawState();
    }

EXPORT_C void CEikButtonBase::SetReportOnPointerDown()
    {
    iButFlags|=KButtonReportOnPointerDown;
    }

EXPORT_C void CEikButtonBase::SetBehavior(TButtonBehavior aType)
    {
    if (aType&EEikButtonReportsOnPointerDown)
		SetReportOnPointerDown();
	iButFlags&=(~KButtonBehaviorMask);
    iButFlags|=(aType&(~EEikButtonReportsOnPointerDown));
    }

EXPORT_C TKeyResponse CEikButtonBase::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
	const TInt code=aKeyEvent.iCode;
	if (code==EKeyDownArrow || code ==EKeyUpArrow)
		return(EKeyWasNotConsumed);
    if (aType!=EEventKey)
        return(EKeyWasConsumed);
	CEikButtonBase::TState oldState=State();
   	switch (code)
        {
	case EKeyLeftArrow:
	case EKeyTab:
    case EKeyRightArrow:
		Animate();
	default:
		;
		}
	if (State()!=oldState)
		ReportEventL(MCoeControlObserver::EEventStateChanged);
    return(EKeyWasConsumed);
	}

EXPORT_C void CEikButtonBase::HandlePointerEventL(const TPointerEvent& aPointerEvent)
    {
	if (iButFlags&EIgnoreNextPointerUp)
		{
		if (aPointerEvent.iType==TPointerEvent::EButton1Up)
			iButFlags&=~EIgnoreNextPointerUp;
		return;
		}
    TDrawState oldDrawState=DrawState();
    TBool report=EFalse;
    TBool clicked=EFalse;
    iButFlags&=(~KButtonPressedMask);
    if (Rect().Contains(aPointerEvent.iPosition))
        {
        if (aPointerEvent.iType!=TPointerEvent::EButton1Up)
            {
			iButFlags|=KButtonPressedMask;
			if (iButFlags&KButtonReportOnPointerDown && aPointerEvent.iType==TPointerEvent::EButton1Down)
				report=ETrue;
            }
        else
            {
            if (!(iButFlags&KButtonReportOnPointerDown))
                report=ETrue;
            clicked=ClickCompleted();
            }
        }
    if (oldDrawState!=DrawState())
		{
        if (!clicked)
    		StateChanged();
        DrawNow();
		}
    if (report)
		{
		iCoeEnv->WsSession().Flush();
        ReportEventL(MCoeControlObserver::EEventStateChanged);
		}
    }

TBool CEikButtonBase::ClickCompleted()
    {
    TButtonBehavior behav=(TButtonBehavior)(iButFlags&KButtonBehaviorMask);
    switch (State())
        {
    case EClear:
        if (behav==EEikButtonStaysClear)
            return(EFalse);
        SetState(iButFlags&KButtonTristate? EIndeterminate: ESet);
        break;
    case ESet:
		if (iButCoord || behav==EEikButtonStaysSet)
            return(EFalse);
        SetState(EClear);
        break;
    case EIndeterminate:
        SetState(ESet);
        break;
        }
    return(ETrue); // means SetState() was called
    }

EXPORT_C void CEikButtonBase::Animate()
    {
    iButFlags|=KButtonPressedMask;
    StateChanged();
    DrawNow();
    iCoeEnv->Flush(KAnimationDelayInMicroSeconds);
    iButFlags&=(~KButtonPressedMask);
    if (!ClickCompleted())
        StateChanged();
    DrawNow();
	iCoeEnv->WsSession().Flush();
    }

EXPORT_C void CEikButtonBase::SetAllowTristate()
    {
    iButFlags|=KButtonAllowTristate;
    }

EXPORT_C void CEikButtonBase::SetIgnoreNextPointerUp()
	{
	iButFlags|=EIgnoreNextPointerUp;
	}

EXPORT_C void CEikButtonBase::Reserved_1()
	{}
EXPORT_C void CEikButtonBase::Reserved_2()
	{}
EXPORT_C void CEikButtonBase::Reserved_3()
	{}

//
// class TEikButtonCoordinator
//

EXPORT_C TEikButtonCoordinator::TEikButtonCoordinator()
	: iChosenButton(NULL)
	{}

EXPORT_C void TEikButtonCoordinator::SetChosenButton(CEikButtonBase* aChosenButton)
	{
	if (iChosenButton==aChosenButton)
		return;
	if (iChosenButton)
		{
		iChosenButton->SetState(CEikButtonBase::EClear);
		iChosenButton->DrawNow();
		}
	iChosenButton=aChosenButton;
	}
