// 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;
    }

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

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

    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;
    }

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


    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, bool bReset,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)\
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)\
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)

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;
    }
}

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();
    return rcWindow.Contains(rcClient) ? rcClient : 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));
}

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()
{
}

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

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();

    return this;
}

void CPWL_Wnd::SetVisible(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;
}

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;
}

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

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

    return false;
}

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

    return false;
}

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;

    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;

    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;

    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;

    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(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();
    }
}

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

void CPWL_Wnd::OnEnabled()
{
}

void CPWL_Wnd::OnDisabled()
{
}

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

    return false;
}

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

    return false;
}

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

    return false;
}

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

    return false;
}
