// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include <map>

#include "../../include/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"

/* -------------------------- CPWL_Timer -------------------------- */

static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap()
{
  // Leak the object at shutdown.
  static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
  return *timeMap;
}

CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached, IFX_SystemHandler* pSystemHandler) :
	m_nTimerID(0),
	m_pAttached(pAttached),
	m_pSystemHandler(pSystemHandler)
{
	ASSERT(m_pAttached != NULL);
	ASSERT(m_pSystemHandler != NULL);
}

CPWL_Timer::~CPWL_Timer()
{
	KillPWLTimer();
}

int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse)
{
    if (m_nTimerID != 0)
        KillPWLTimer();
    m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);

    GetPWLTimeMap()[m_nTimerID] = this;
    return m_nTimerID;
}

void CPWL_Timer::KillPWLTimer()
{
    if (m_nTimerID == 0)
        return;

    m_pSystemHandler->KillTimer(m_nTimerID);
    GetPWLTimeMap().erase(m_nTimerID);
    m_nTimerID = 0;
}

void CPWL_Timer::TimerProc(int32_t idEvent)
{
    auto it = GetPWLTimeMap().find(idEvent);
    if (it == GetPWLTimeMap().end())
        return;

    CPWL_Timer* pTimer = it->second;
    if (pTimer->m_pAttached)
        pTimer->m_pAttached->TimerProc();
}

/* -------------------------- CPWL_TimerHandler -------------------------- */

CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL)
{
}

CPWL_TimerHandler::~CPWL_TimerHandler()
{
    delete m_pTimer;
}

void CPWL_TimerHandler::BeginTimer(int32_t nElapse)
{
	if (!m_pTimer)
		m_pTimer = new CPWL_Timer(this, GetSystemHandler());

	if (m_pTimer)
		m_pTimer->SetPWLTimer(nElapse);
}

void CPWL_TimerHandler::EndTimer()
{
	if (m_pTimer)
		m_pTimer->KillPWLTimer();
}

void CPWL_TimerHandler::TimerProc()
{
}

/* --------------------------- CPWL_MsgControl ---------------------------- */

class CPWL_MsgControl
{
	friend class CPWL_Wnd;

public:
	CPWL_MsgControl(CPWL_Wnd * pWnd)
	{
//		PWL_TRACE("new CPWL_MsgControl\n");
		m_pCreatedWnd = pWnd;
		Default();
	}

	~CPWL_MsgControl()
	{
//		PWL_TRACE("~CPWL_MsgControl\n");
		Default();
	}

	void Default()
	{
		m_aMousePath.RemoveAll();
		m_aKeyboardPath.RemoveAll();
		m_pMainMouseWnd = NULL;
		m_pMainKeyboardWnd = NULL;
	}

	FX_BOOL IsWndCreated(const CPWL_Wnd * pWnd) const
	{
		return m_pCreatedWnd == pWnd;
	}

	FX_BOOL IsMainCaptureMouse(const CPWL_Wnd * pWnd) const
	{
		return pWnd == m_pMainMouseWnd;
	}

	FX_BOOL IsWndCaptureMouse(const CPWL_Wnd * pWnd) const
	{
		if (pWnd)
			for( int32_t i=0,sz=m_aMousePath.GetSize(); i<sz; i++)
				if (m_aMousePath.GetAt(i) == pWnd)
					return TRUE;

		return FALSE;
	}

	FX_BOOL IsMainCaptureKeyboard(const CPWL_Wnd * pWnd) const
	{
		return pWnd == m_pMainKeyboardWnd;
	}


	FX_BOOL IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const
	{
		if (pWnd)
			for( int32_t i=0,sz=m_aKeyboardPath.GetSize(); i<sz; i++)
				if (m_aKeyboardPath.GetAt(i) == pWnd)
					return TRUE;

		return FALSE;
	}

	void SetFocus(CPWL_Wnd * pWnd)
	{
		m_aKeyboardPath.RemoveAll();

		if (pWnd)
		{
			m_pMainKeyboardWnd = pWnd;

			CPWL_Wnd * pParent = pWnd;
			while (pParent)
			{
				m_aKeyboardPath.Add(pParent);
				pParent = pParent->GetParentWindow();
			}

			pWnd->OnSetFocus();
		}
	}

	void KillFocus()
	{
		if (m_aKeyboardPath.GetSize() > 0)
			if (CPWL_Wnd* pWnd = m_aKeyboardPath.GetAt(0))
				pWnd->OnKillFocus();

		m_pMainKeyboardWnd = NULL;
		m_aKeyboardPath.RemoveAll();
	}

	void SetCapture(CPWL_Wnd * pWnd)
	{
		m_aMousePath.RemoveAll();

		if (pWnd)
		{
			m_pMainMouseWnd = pWnd;

			CPWL_Wnd * pParent = pWnd;
			while (pParent)
			{
				m_aMousePath.Add(pParent);
				pParent = pParent->GetParentWindow();
			}
		}
	}

	void ReleaseCapture()
	{
		m_pMainMouseWnd = NULL;
		m_aMousePath.RemoveAll();
	}

private:
	CFX_ArrayTemplate<CPWL_Wnd*>	m_aMousePath;
	CFX_ArrayTemplate<CPWL_Wnd*>	m_aKeyboardPath;
	CPWL_Wnd*						m_pCreatedWnd;
	CPWL_Wnd*						m_pMainMouseWnd;
	CPWL_Wnd*						m_pMainKeyboardWnd;
};

/* --------------------------- CPWL_Wnd ---------------------------- */

CPWL_Wnd::CPWL_Wnd() :
	m_pVScrollBar(NULL),
	m_rcWindow(),
	m_rcClip(),
	m_bCreated(FALSE),
	m_bVisible(FALSE),
	m_bNotifying(FALSE),
	m_bEnabled(TRUE)
{
}

CPWL_Wnd::~CPWL_Wnd()
{
	ASSERT(m_bCreated == FALSE);
}

CFX_ByteString CPWL_Wnd::GetClassName() const
{
	return "CPWL_Wnd";
}

void CPWL_Wnd::Create(const PWL_CREATEPARAM & cp)
{
	if (!IsValid())
	{
		m_sPrivateParam = cp;

		OnCreate(m_sPrivateParam);

		m_sPrivateParam.rcRectWnd.Normalize();
		m_rcWindow = m_sPrivateParam.rcRectWnd;
		m_rcClip = CPWL_Utils::InflateRect(m_rcWindow,1.0f);

		CreateMsgControl();

		if (m_sPrivateParam.pParentWnd)
			m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);

		PWL_CREATEPARAM ccp = m_sPrivateParam;

		ccp.dwFlags &= 0xFFFF0000L; //remove sub styles
		ccp.mtChild = CPDF_Matrix(1,0,0,1,0,0);

		CreateScrollBar(ccp);
		CreateChildWnd(ccp);

		m_bVisible = HasFlag(PWS_VISIBLE);

		OnCreated();

		RePosChildWnd();
		m_bCreated = TRUE;
	}
}

void CPWL_Wnd::OnCreate(PWL_CREATEPARAM & cp)
{
}

void CPWL_Wnd::OnCreated()
{
}

void CPWL_Wnd::OnDestroy()
{
}

void CPWL_Wnd::Destroy()
{
	KillFocus();

	OnDestroy();

	if (m_bCreated)
	{
		for (int32_t i = m_aChildren.GetSize()-1; i >= 0; i --)
		{
			if (CPWL_Wnd * pChild = m_aChildren[i])
			{
				pChild->Destroy();
				delete pChild;
				pChild = NULL;
			}
		}

		if (m_sPrivateParam.pParentWnd)
			m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
		m_bCreated = FALSE;
	}

	DestroyMsgControl();

	FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
	m_aChildren.RemoveAll();
	m_pVScrollBar = NULL;
}

void CPWL_Wnd::Move(const CPDF_Rect & rcNew, FX_BOOL bReset,FX_BOOL bRefresh)
{
	if (IsValid())
	{
		CPDF_Rect rcOld = GetWindowRect();

		m_rcWindow = rcNew;
		m_rcWindow.Normalize();

		if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
			rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom)
		{
			if (bReset)
			{
				RePosChildWnd();
			}

		}
		if (bRefresh)
		{
			InvalidateRectMove(rcOld,rcNew);
		}

		m_sPrivateParam.rcRectWnd = m_rcWindow;
	}
}

void  CPWL_Wnd::InvalidateRectMove(const CPDF_Rect & rcOld, const CPDF_Rect & rcNew)
{
	CPDF_Rect rcUnion = rcOld;
	rcUnion.Union(rcNew);

	InvalidateRect(&rcUnion);
}

void CPWL_Wnd::GetAppearanceStream(CFX_ByteString & sAppStream)
{
	if (IsValid())
	{
		CFX_ByteTextBuf sTextBuf;
		GetAppearanceStream(sTextBuf);
		sAppStream += sTextBuf.GetByteString();
	}
}

void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	if (IsValid() && IsVisible())
	{
		GetThisAppearanceStream(sAppStream);
		GetChildAppearanceStream(sAppStream);
	}
}

//if don't set,Get default apperance stream
void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
    CPDF_Rect rectWnd = GetWindowRect();
    if (!rectWnd.IsEmpty()) {
        CFX_ByteTextBuf sThis;

        if (HasFlag(PWS_BACKGROUND))
            sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());

        if (HasFlag(PWS_BORDER)) {
            sThis << CPWL_Utils::GetBorderAppStream(
                rectWnd,
                (FX_FLOAT)GetBorderWidth(),
                GetBorderColor(),
                GetBorderLeftTopColor(GetBorderStyle()),
                GetBorderRightBottomColor(GetBorderStyle()),
                GetBorderStyle(),
                GetBorderDash());
        }

        sAppStream << sThis;
    }
}

void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
		{
			pChild->GetAppearanceStream(sAppStream);
		}
	}
}

void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	if (IsValid() && IsVisible())
	{
		DrawThisAppearance(pDevice,pUser2Device);
		DrawChildAppearance(pDevice,pUser2Device);
	}
}

void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	CPDF_Rect rectWnd = GetWindowRect();
	if (!rectWnd.IsEmpty())
	{
		if (HasFlag(PWS_BACKGROUND))
		{
			CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rectWnd,(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
			CPWL_Utils::DrawFillRect(pDevice,pUser2Device,rcClient, GetBackgroundColor(), GetTransparency());
		}

		if (HasFlag(PWS_BORDER))
			CPWL_Utils::DrawBorder(pDevice,
								pUser2Device,
								rectWnd,
								(FX_FLOAT)GetBorderWidth(),
								GetBorderColor(),
								GetBorderLeftTopColor(GetBorderStyle()),
								GetBorderRightBottomColor(GetBorderStyle()),
								GetBorderStyle(),
								GetBorderDash(),
								GetTransparency());
	}
}

void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
		{
			CPDF_Matrix mt = pChild->GetChildMatrix();
			if (mt.IsIdentity())
			{
				pChild->DrawAppearance(pDevice,pUser2Device);
			}
			else
			{
				mt.Concat(*pUser2Device);
				pChild->DrawAppearance(pDevice,&mt);
			}
		}
	}
}

void CPWL_Wnd::InvalidateRect(CPDF_Rect* pRect)
{
	if (IsValid())
	{
		CPDF_Rect rcRefresh = pRect ? *pRect : GetWindowRect();

		if (!HasFlag(PWS_NOREFRESHCLIP))
		{
			CPDF_Rect rcClip = GetClipRect();
			if (!rcClip.IsEmpty())
			{
				rcRefresh.Intersect(rcClip);
			}
		}

		FX_RECT rcWin = PWLtoWnd(rcRefresh);
		rcWin.left -= PWL_INVALIDATE_INFLATE;
		rcWin.top -= PWL_INVALIDATE_INFLATE;
		rcWin.right += PWL_INVALIDATE_INFLATE;
		rcWin.bottom += PWL_INVALIDATE_INFLATE;

		if (IFX_SystemHandler* pSH = GetSystemHandler())
		{
			if (FX_HWND hWnd = GetAttachedHWnd())
			{
				pSH->InvalidateRect(hWnd, rcWin);
			}
		}
	}
}

#define PWL_IMPLEMENT_KEY_METHOD(key_method_name)\
FX_BOOL CPWL_Wnd::key_method_name(FX_WORD nChar, FX_DWORD nFlag)\
{\
	if (IsValid() && IsVisible() && IsEnabled())\
	{\
		if (IsWndCaptureKeyboard(this))\
		{\
			for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)\
			{\
				if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))\
				{\
					if (IsWndCaptureKeyboard(pChild))\
					{\
						return pChild->key_method_name(nChar,nFlag);\
					}\
				}\
			}\
		}\
	}\
	return FALSE;\
}

#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)\
FX_BOOL CPWL_Wnd::mouse_method_name(const CPDF_Point & point, FX_DWORD nFlag)\
{\
	if (IsValid() && IsVisible() && IsEnabled())\
	{\
		if (IsWndCaptureMouse(this))\
		{\
			for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)\
			{\
				if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))\
				{\
					if (IsWndCaptureMouse(pChild))\
					{\
						return pChild->mouse_method_name(pChild->ParentToChild(point),nFlag);\
					}\
				}\
			}\
			SetCursor();\
		}\
		else\
		{\
			for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)\
			{\
				if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))\
				{\
					if (pChild->WndHitTest(pChild->ParentToChild(point)))\
					{\
						return pChild->mouse_method_name(pChild->ParentToChild(point),nFlag);\
					}\
				}\
			}\
			if (WndHitTest(point))\
				SetCursor();\
		}\
	}\
	return FALSE;\
}

PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)
PWL_IMPLEMENT_KEY_METHOD(OnChar)

PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)

FX_BOOL	CPWL_Wnd::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
{
	if (IsValid() && IsVisible() && IsEnabled())
	{
		SetCursor();
		if (IsWndCaptureKeyboard(this))
		{
			for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
			{
				if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
				{
					if (IsWndCaptureKeyboard(pChild))
					{
						return pChild->OnMouseWheel(zDelta,pChild->ParentToChild(point), nFlag);
					}
				}
			}
		}
	}
	return FALSE;
}

void CPWL_Wnd::AddChild(CPWL_Wnd * pWnd)
{
	m_aChildren.Add(pWnd);
}

void CPWL_Wnd::RemoveChild(CPWL_Wnd * pWnd)
{
	for (int32_t i = m_aChildren.GetSize()-1; i >= 0; i --)
	{
		if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
		{
			if (pChild == pWnd)
			{
				m_aChildren.RemoveAt(i);
				break;
			}
		}
	}
}

void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, intptr_t wParam, intptr_t lParam)
{
	switch (msg)
	{
	case PNM_ADDCHILD:
		AddChild(pWnd);
		break;
	case PNM_REMOVECHILD:
		RemoveChild(pWnd);
		break;
	default:
		break;
	}
}

FX_BOOL CPWL_Wnd::IsValid() const
{
	return m_bCreated;
}

PWL_CREATEPARAM CPWL_Wnd::GetCreationParam() const
{
	return m_sPrivateParam;
}

CPWL_Wnd* CPWL_Wnd::GetParentWindow() const
{
	return m_sPrivateParam.pParentWnd;
}

CPDF_Rect CPWL_Wnd::GetOriginWindowRect() const
{
	return m_sPrivateParam.rcRectWnd;
}

CPDF_Rect CPWL_Wnd::GetWindowRect() const
{
	return m_rcWindow;
}

CPDF_Rect CPWL_Wnd::GetClientRect() const
{
	CPDF_Rect rcWindow = GetWindowRect();
	CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rcWindow,(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));

	if (CPWL_ScrollBar * pVSB = GetVScrollBar())
		rcClient.right -= pVSB->GetScrollBarWidth();

	rcClient.Normalize();

	if (rcWindow.Contains(rcClient))
		return rcClient;
	else
		return CPDF_Rect();
}

CPDF_Point CPWL_Wnd::GetCenterPoint() const
{
	CPDF_Rect rcClient = GetClientRect();

	return CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
		(rcClient.top + rcClient.bottom) * 0.5f);
}

CPDF_Rect CPWL_Wnd::GetClientCenterSquare() const
{
	return CPWL_Utils::GetCenterSquare(GetClientRect());
}

CPDF_Rect CPWL_Wnd::GetWindowCenterSquare() const
{
	return CPWL_Utils::GetCenterSquare(CPWL_Utils::DeflateRect(GetWindowRect(),0.1f));
}

FX_BOOL CPWL_Wnd::HasFlag(FX_DWORD dwFlags) const
{
	return (m_sPrivateParam.dwFlags & dwFlags) != 0;
}

void CPWL_Wnd::RemoveFlag(FX_DWORD dwFlags)
{
	m_sPrivateParam.dwFlags &= ~dwFlags;
}

void CPWL_Wnd::AddFlag(FX_DWORD dwFlags)
{
	m_sPrivateParam.dwFlags |= dwFlags;
}

CPWL_Color CPWL_Wnd::GetBackgroundColor() const
{
	return m_sPrivateParam.sBackgroundColor;
}

void CPWL_Wnd::SetBackgroundColor(const CPWL_Color & color)
{
	m_sPrivateParam.sBackgroundColor = color;
}

void CPWL_Wnd::SetTextColor(const CPWL_Color & color)
{
	m_sPrivateParam.sTextColor = color;
}

void CPWL_Wnd::SetTextStrokeColor(const CPWL_Color & color)
{
	m_sPrivateParam.sTextStrokeColor = color;
}

CPWL_Color CPWL_Wnd::GetTextColor() const
{
	return m_sPrivateParam.sTextColor;
}

CPWL_Color CPWL_Wnd::GetTextStrokeColor() const
{
	return m_sPrivateParam.sTextStrokeColor;
}

int32_t CPWL_Wnd::GetBorderStyle() const
{
	return m_sPrivateParam.nBorderStyle;
}

void CPWL_Wnd::SetBorderStyle(int32_t nBorderStyle)
{
	if (HasFlag(PWS_BORDER))
		m_sPrivateParam.nBorderStyle = nBorderStyle;
}

int32_t CPWL_Wnd::GetBorderWidth() const
{
	if (HasFlag(PWS_BORDER))
		return m_sPrivateParam.dwBorderWidth;

	return 0;
}

int32_t CPWL_Wnd::GetInnerBorderWidth() const
{
	/*
	switch (GetBorderStyle())
	{
	case PBS_BEVELED:
	case PBS_INSET:
		return GetBorderWidth() / 2;
	}
	*/
	return 0;
}

void CPWL_Wnd::SetBorderWidth(int32_t nBorderWidth)
{
	if (HasFlag(PWS_BORDER))
		m_sPrivateParam.dwBorderWidth = nBorderWidth;
}

CPWL_Color CPWL_Wnd::GetBorderColor() const
{
	if (HasFlag(PWS_BORDER))
		return m_sPrivateParam.sBorderColor;

	return CPWL_Color();
}

void CPWL_Wnd::SetBorderColor(const CPWL_Color & color)
{
	if (HasFlag(PWS_BORDER))
		m_sPrivateParam.sBorderColor = color;
}

CPWL_Dash CPWL_Wnd::GetBorderDash() const
{
	return m_sPrivateParam.sDash;
}

void* CPWL_Wnd::GetAttachedData() const
{
	return m_sPrivateParam.pAttachedData;
}

void CPWL_Wnd::SetBorderDash(const CPWL_Dash & sDash)
{
	if (HasFlag(PWS_BORDER))
		m_sPrivateParam.sDash = sDash;
}

CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const
{
	if (HasFlag(PWS_VSCROLL))
		return m_pVScrollBar;

	return NULL;
}

void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM & cp)
{
	CreateVScrollBar(cp);
}

void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM & cp)
{
	if (!m_pVScrollBar && HasFlag(PWS_VSCROLL))
	{
		PWL_CREATEPARAM scp = cp;

		//flags
		scp.dwFlags = PWS_CHILD| PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;

		scp.pParentWnd = this;
		scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
		scp.eCursorType = FXCT_ARROW;
		scp.nTransparency = PWL_SCROLLBAR_TRANSPARANCY;

		if ((m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL)))
			m_pVScrollBar->Create(scp);
	}
}

void CPWL_Wnd::SetCapture()
{
	if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
		pMsgCtrl->SetCapture(this);
}

void CPWL_Wnd::ReleaseCapture()
{
	for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
		if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
			pChild->ReleaseCapture();

	if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
		pMsgCtrl->ReleaseCapture();
}

void CPWL_Wnd::SetFocus()
{
	if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
	{
		if (!pMsgCtrl->IsMainCaptureKeyboard(this))
			pMsgCtrl->KillFocus();
		pMsgCtrl->SetFocus(this);
	}
}

void CPWL_Wnd::KillFocus()
{
	if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
	{
		if (pMsgCtrl->IsWndCaptureKeyboard(this))
			pMsgCtrl->KillFocus();
	}
}

void CPWL_Wnd::OnSetFocus()
{
}

void CPWL_Wnd::OnKillFocus()
{
}

FX_BOOL	CPWL_Wnd::WndHitTest(const CPDF_Point & point) const
{
	return IsValid() && IsVisible() && GetWindowRect().Contains(point.x,point.y);
}

FX_BOOL CPWL_Wnd::ClientHitTest(const CPDF_Point & point) const
{
	return IsValid() && IsVisible() && GetClientRect().Contains(point.x,point.y);
}

const CPWL_Wnd * CPWL_Wnd::GetRootWnd() const
{
	if (m_sPrivateParam.pParentWnd)
		return m_sPrivateParam.pParentWnd->GetRootWnd();
	else
		return this;
}

void CPWL_Wnd::SetVisible(FX_BOOL bVisible)
{
	if (IsValid())
	{
		for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
		{
			if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
			{
				pChild->SetVisible(bVisible);
			}
		}

		if (bVisible != m_bVisible)
		{
			m_bVisible = bVisible;
			RePosChildWnd();
			InvalidateRect();
		}
	}
}

void CPWL_Wnd::SetClipRect(const CPDF_Rect & rect)
{
	m_rcClip = rect;
	m_rcClip.Normalize();
}

CPDF_Rect CPWL_Wnd::GetClipRect() const
{
	return m_rcClip;
}

FX_BOOL	CPWL_Wnd::IsReadOnly() const
{
	return HasFlag(PWS_READONLY);
}

void CPWL_Wnd::RePosChildWnd()
{
	CPDF_Rect rcContent = CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));

	CPWL_ScrollBar * pVSB = GetVScrollBar();

	CPDF_Rect rcVScroll = CPDF_Rect(rcContent.right - PWL_SCROLLBAR_WIDTH,
							rcContent.bottom,
							rcContent.right-1.0f,
							rcContent.top);

	if (pVSB) pVSB->Move(rcVScroll,TRUE,FALSE);
}

void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
}

void CPWL_Wnd::SetCursor()
{
	if (IsValid())
	{
		if (IFX_SystemHandler* pSH = GetSystemHandler())
		{
			int32_t nCursorType = GetCreationParam().eCursorType;
			pSH->SetCursor(nCursorType);
		}
	}
}

void CPWL_Wnd::CreateMsgControl()
{
	if (!m_sPrivateParam.pMsgControl)
		m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
}

void CPWL_Wnd::DestroyMsgControl()
{
	if (CPWL_MsgControl* pMsgControl = GetMsgControl())
		if (pMsgControl->IsWndCreated(this))
			delete pMsgControl;
}

CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const
{
	return m_sPrivateParam.pMsgControl;
}

FX_BOOL CPWL_Wnd::IsCaptureMouse() const
{
	return IsWndCaptureMouse(this);
}

FX_BOOL CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd * pWnd) const
{
	if (CPWL_MsgControl * pCtrl = GetMsgControl())
		return pCtrl->IsWndCaptureMouse(pWnd);

	return FALSE;
}

FX_BOOL CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const
{
	if (CPWL_MsgControl * pCtrl = GetMsgControl())
		return pCtrl->IsWndCaptureKeyboard(pWnd);

	return FALSE;
}

FX_BOOL CPWL_Wnd::IsFocused() const
{
	if (CPWL_MsgControl * pCtrl = GetMsgControl())
		return pCtrl->IsMainCaptureKeyboard(this);

	return FALSE;
}

CPDF_Rect CPWL_Wnd::GetFocusRect() const
{
	return CPWL_Utils::InflateRect(GetWindowRect(),1);
}

FX_FLOAT CPWL_Wnd::GetFontSize() const
{
	return m_sPrivateParam.fFontSize;
}

void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize)
{
	m_sPrivateParam.fFontSize = fFontSize;
}

IFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const
{
	return m_sPrivateParam.pSystemHandler;
}

IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const
{
	return m_sPrivateParam.pFocusHandler;
}

IPWL_Provider* CPWL_Wnd::GetProvider() const
{
	return m_sPrivateParam.pProvider;
}

IFX_Edit_FontMap* CPWL_Wnd::GetFontMap() const
{
	return m_sPrivateParam.pFontMap;
}

CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(int32_t nBorderStyle) const
{
	CPWL_Color color;

	switch (nBorderStyle)
	{
		case PBS_SOLID:
			break;
		case PBS_DASH:
			break;
		case PBS_BEVELED:
			color = CPWL_Color(COLORTYPE_GRAY,1);
			break;
		case PBS_INSET:
			color = CPWL_Color(COLORTYPE_GRAY,0.5f);
			break;
		case PBS_UNDERLINED:
			break;
	}

	return color;
}

CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(int32_t nBorderStyle) const
{
	CPWL_Color color;

	switch (nBorderStyle)
	{
		case PBS_SOLID:
			break;
		case PBS_DASH:
			break;
		case PBS_BEVELED:
			color = CPWL_Utils::DevideColor(GetBackgroundColor(),2);
			break;
		case PBS_INSET:
			color = CPWL_Color(COLORTYPE_GRAY,0.75f);
			break;
		case PBS_UNDERLINED:
			break;
	}

	return color;
}

/* ----------------------------------------------------------------- */

int32_t CPWL_Wnd::GetTransparency()
{
	return m_sPrivateParam.nTransparency;
}

void CPWL_Wnd::SetTransparency(int32_t nTransparency)
{
	for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
		{
			pChild->SetTransparency(nTransparency);
		}
	}

	m_sPrivateParam.nTransparency = nTransparency;
}

CPDF_Matrix	CPWL_Wnd::GetWindowMatrix() const
{
	CPDF_Matrix mt = GetChildToRoot();

	if (IPWL_Provider* pProvider = GetProvider())
	{
		mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
		return mt;
	}

	return mt;
}

void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, int32_t& x, int32_t& y) const
{
	CPDF_Matrix mt = GetWindowMatrix();
	CPDF_Point pt = point;
	mt.Transform(pt.x,pt.y);
	x = (int32_t)(pt.x+0.5);
	y = (int32_t)(pt.y+0.5);
}

FX_RECT CPWL_Wnd::PWLtoWnd(const CPDF_Rect & rect) const
{
	CPDF_Rect rcTemp = rect;
	CPDF_Matrix mt = GetWindowMatrix();
	mt.TransformRect(rcTemp);
	return FX_RECT((int32_t)(rcTemp.left+0.5), (int32_t)(rcTemp.bottom+0.5), (int32_t)(rcTemp.right+0.5), (int32_t)(rcTemp.top+0.5));
}

FX_HWND CPWL_Wnd::GetAttachedHWnd() const
{
	return m_sPrivateParam.hAttachedWnd;
}

CPDF_Point CPWL_Wnd::ChildToParent(const CPDF_Point& point) const
{
	CPDF_Matrix mt = GetChildMatrix();
	if (mt.IsIdentity())
		return point;
	else
	{
		CPDF_Point pt = point;
		mt.Transform(pt.x,pt.y);
		return pt;
	}
}

CPDF_Rect CPWL_Wnd::ChildToParent(const CPDF_Rect& rect) const
{
	CPDF_Matrix mt = GetChildMatrix();
	if (mt.IsIdentity())
		return rect;
	else
	{
		CPDF_Rect rc = rect;
		mt.TransformRect(rc);
		return rc;
	}
}

CPDF_Point CPWL_Wnd::ParentToChild(const CPDF_Point& point) const
{
	CPDF_Matrix mt = GetChildMatrix();
	if (mt.IsIdentity())
		return point;
	else
	{
		mt.SetReverse(mt);
		CPDF_Point pt = point;
		mt.Transform(pt.x,pt.y);
		return pt;
	}
}

CPDF_Rect CPWL_Wnd::ParentToChild(const CPDF_Rect& rect) const
{
	CPDF_Matrix mt = GetChildMatrix();
	if (mt.IsIdentity())
		return rect;
	else
	{
		mt.SetReverse(mt);
		CPDF_Rect rc = rect;
		mt.TransformRect(rc);
		return rc;
	}
}

CPDF_Matrix CPWL_Wnd::GetChildToRoot() const
{
	CPDF_Matrix mt(1,0,0,1,0,0);

	if (HasFlag(PWS_CHILD))
	{
		const CPWL_Wnd* pParent = this;
		while (pParent)
		{
			mt.Concat(pParent->GetChildMatrix());
			pParent = pParent->GetParentWindow();
		}
	}

	return mt;
}

CPDF_Matrix CPWL_Wnd::GetChildMatrix() const
{
	if (HasFlag(PWS_CHILD))
		return m_sPrivateParam.mtChild;

	return CPDF_Matrix(1,0,0,1,0,0);
}

void CPWL_Wnd::SetChildMatrix(const CPDF_Matrix& mt)
{
	m_sPrivateParam.mtChild = mt;
}

const CPWL_Wnd*	CPWL_Wnd::GetFocused() const
{
	if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
	{
		return pMsgCtrl->m_pMainKeyboardWnd;
	}

	return NULL;
}

void CPWL_Wnd::EnableWindow(FX_BOOL bEnable)
{
	if (m_bEnabled != bEnable)
	{
		for (int32_t i=0,sz=m_aChildren.GetSize(); i<sz; i++)
		{
			if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
			{
				pChild->EnableWindow(bEnable);
			}
		}

		m_bEnabled = bEnable;

		if (bEnable)
			OnEnabled();
		else
			OnDisabled();
	}
}

FX_BOOL CPWL_Wnd::IsEnabled()
{
	return m_bEnabled;
}

void CPWL_Wnd::OnEnabled()
{
}

void CPWL_Wnd::OnDisabled()
{
}

FX_BOOL CPWL_Wnd::IsCTRLpressed(FX_DWORD nFlag) const
{
	if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
	{
		return pSystemHandler->IsCTRLKeyDown(nFlag);
	}

	return FALSE;
}

FX_BOOL	CPWL_Wnd::IsSHIFTpressed(FX_DWORD nFlag) const
{
	if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
	{
		return pSystemHandler->IsSHIFTKeyDown(nFlag);
	}

	return FALSE;
}

FX_BOOL	CPWL_Wnd::IsALTpressed(FX_DWORD nFlag) const
{
	if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
	{
		return pSystemHandler->IsALTKeyDown(nFlag);
	}

	return FALSE;
}

FX_BOOL	CPWL_Wnd::IsINSERTpressed(FX_DWORD nFlag) const
{
	if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
	{
		return pSystemHandler->IsINSERTKeyDown(nFlag);
	}

	return FALSE;
}

