// 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 "../../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 CFX_MapPtrTemplate<FX_INT32, CPWL_Timer*>	g_TimeMap;

CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached, IFX_SystemHandler* pSystemHandler) : 
	m_pAttached(pAttached),
	m_nTimerID(0),
	m_pSystemHandler(pSystemHandler)
{
	ASSERT(m_pAttached != NULL);
	ASSERT(m_pSystemHandler != NULL);
}

CPWL_Timer::~CPWL_Timer()
{
	KillPWLTimer();
}

FX_INT32 CPWL_Timer::SetPWLTimer(FX_INT32 nElapse)
{	
	if (m_nTimerID != 0) KillPWLTimer();
	m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
	g_TimeMap.SetAt(m_nTimerID, this);
	return m_nTimerID;
}

void CPWL_Timer::KillPWLTimer()
{
	if (m_nTimerID != 0)
	{
		m_pSystemHandler->KillTimer(m_nTimerID);
		g_TimeMap.RemoveKey(m_nTimerID);
		m_nTimerID = 0;
	}
}

void CPWL_Timer::TimerProc(FX_INT32 idEvent)
{
	CPWL_Timer* pTimer = NULL;
	if (g_TimeMap.Lookup(idEvent, pTimer))
	{
		if (pTimer)
		{			
			if (pTimer->m_pAttached) 
				pTimer->m_pAttached->TimerProc();
		}
	}
}

/* -------------------------- CPWL_TimerHandler -------------------------- */

CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL)
{
}

CPWL_TimerHandler::~CPWL_TimerHandler()
{
	if (m_pTimer) delete m_pTimer;
}

void CPWL_TimerHandler::BeginTimer(FX_INT32 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( FX_INT32 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( FX_INT32 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 (FX_INT32 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 = this->GetWindowRect();

		m_rcWindow = rcNew;
		m_rcWindow.Normalize();
		//m_rcClip = CPWL_Utils::InflateRect(m_rcWindow,1.0f); //for special caret 

		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);

	/*
	CPDF_Rect SubArray[4]; 

	rcOld.Substract4(rcNew,SubArray);
	for (FX_INT32 i=0;i<4;i++)
	{
		if (SubArray[i].left == 0 &&
			SubArray[i].right == 0 &&
			SubArray[i].top == 0 &&
			SubArray[i].bottom == 0)continue;

		InvalidateRect(&CPWL_Utils::InflateRect(SubArray[i],2));
	}

	rcNew.Substract4(rcOld,SubArray);
	for (FX_INT32 j=0;j<4;j++)
	{
		if (SubArray[j].left == 0 &&
			SubArray[j].right == 0 &&
			SubArray[j].top == 0 &&
			SubArray[j].bottom == 0)continue;

		InvalidateRect(&CPWL_Utils::InflateRect(SubArray[j],2));
	}
	*/
}

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,this->GetBackgroundColor());

		if (HasFlag(PWS_BORDER))
			sThis << CPWL_Utils::GetBorderAppStream(rectWnd,
									(FX_FLOAT)GetBorderWidth(),
									GetBorderColor(),
									this->GetBorderLeftTopColor(this->GetBorderStyle()),
									this->GetBorderRightBottomColor(this->GetBorderStyle()),
									this->GetBorderStyle(),
									this->GetBorderDash());

		sAppStream << sThis;
	}
}

void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	for (FX_INT32 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,this->GetBackgroundColor(),GetTransparency());
		}

		if (HasFlag(PWS_BORDER))
			CPWL_Utils::DrawBorder(pDevice,
								pUser2Device,
								rectWnd,
								(FX_FLOAT)GetBorderWidth(),
								GetBorderColor(),
								this->GetBorderLeftTopColor(this->GetBorderStyle()),
								this->GetBorderRightBottomColor(this->GetBorderStyle()),
								this->GetBorderStyle(),
								this->GetBorderDash(),
								GetTransparency());								
	}
}

void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	for (FX_INT32 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 (FX_INT32 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 (FX_INT32 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 (FX_INT32 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 (this->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(OnRButtonDblClk)
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 (FX_INT32 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 (FX_INT32 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, FX_INTPTR wParam, FX_INTPTR lParam)
{
	switch (msg)
	{
	case PNM_ADDCHILD:
		this->AddChild(pWnd);
		break;
	case PNM_REMOVECHILD:
		this->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 = this->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;
}

FX_INT32 CPWL_Wnd::GetBorderStyle() const
{
	return m_sPrivateParam.nBorderStyle;
}

void CPWL_Wnd::SetBorderStyle(FX_INT32 nBorderStyle)
{
	if (HasFlag(PWS_BORDER))
		m_sPrivateParam.nBorderStyle = nBorderStyle;
}

FX_INT32 CPWL_Wnd::GetBorderWidth() const
{
	if (HasFlag(PWS_BORDER))
		return m_sPrivateParam.dwBorderWidth;

	return 0;
}

FX_INT32 CPWL_Wnd::GetInnerBorderWidth() const
{
	/*
	switch (GetBorderStyle())
	{
	case PBS_BEVELED:
	case PBS_INSET:
		return GetBorderWidth() / 2;
	}
	*/
	return 0;
}

void CPWL_Wnd::SetBorderWidth(FX_INT32 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 (FX_INT32 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 (FX_INT32 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 = this->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())
		{
			FX_INT32 nCursorType = this->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(this->GetWindowRect(),1);
}

FX_FLOAT CPWL_Wnd::GetFontSize() const
{
	return this->m_sPrivateParam.fFontSize;
}

void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize)
{
	this->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(FX_INT32 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(FX_INT32 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;
}

/* ----------------------------------------------------------------- */

FX_INT32 CPWL_Wnd::GetTransparency()
{
	return m_sPrivateParam.nTransparency;
}

void CPWL_Wnd::SetTransparency(FX_INT32 nTransparency)
{
	for (FX_INT32 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 = this->GetChildToRoot();

	if (IPWL_Provider* pProvider = GetProvider())
	{
		mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
		return mt;
	}

/*
	if (CReader_App* pApp = CPWL_Module::GetReaderApp())
		if (CReader_Document* pDocument = pApp->GetCurrentDocument())
			if (CReader_DocView* pDocView = pDocument->GetCurrentDocView())
			{
				CPDF_Matrix mtPageView;
				pDocView->GetCurrentMatrix(mtPageView);
				mt.Concat(mtPageView);
				return mt;
			}		
			
*/

	return mt;
}

void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, FX_INT32& x, FX_INT32& y) const
{
	CPDF_Matrix mt = GetWindowMatrix();
	CPDF_Point pt = point;
	mt.Transform(pt.x,pt.y);
	x = (FX_INT32)(pt.x+0.5);
	y = (FX_INT32)(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((FX_INT32)(rcTemp.left+0.5), (FX_INT32)(rcTemp.bottom+0.5), (FX_INT32)(rcTemp.right+0.5), (FX_INT32)(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 (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
		{
			if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
			{
				pChild->EnableWindow(bEnable);
			}
		}

		this->m_bEnabled = bEnable;

		if (bEnable)
			this->OnEnabled();
		else
			this->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;
}

