Home | History | Annotate | Download | only in pdfwindow
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include <map>
      8 
      9 #include "fpdfsdk/include/pdfwindow/PWL_ScrollBar.h"
     10 #include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
     11 #include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"
     12 
     13 static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
     14   // Leak the object at shutdown.
     15   static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
     16   return *timeMap;
     17 }
     18 
     19 CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
     20                        IFX_SystemHandler* pSystemHandler)
     21     : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
     22   ASSERT(m_pAttached);
     23   ASSERT(m_pSystemHandler);
     24 }
     25 
     26 CPWL_Timer::~CPWL_Timer() {
     27   KillPWLTimer();
     28 }
     29 
     30 int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
     31   if (m_nTimerID != 0)
     32     KillPWLTimer();
     33   m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
     34 
     35   GetPWLTimeMap()[m_nTimerID] = this;
     36   return m_nTimerID;
     37 }
     38 
     39 void CPWL_Timer::KillPWLTimer() {
     40   if (m_nTimerID == 0)
     41     return;
     42 
     43   m_pSystemHandler->KillTimer(m_nTimerID);
     44   GetPWLTimeMap().erase(m_nTimerID);
     45   m_nTimerID = 0;
     46 }
     47 
     48 void CPWL_Timer::TimerProc(int32_t idEvent) {
     49   auto it = GetPWLTimeMap().find(idEvent);
     50   if (it == GetPWLTimeMap().end())
     51     return;
     52 
     53   CPWL_Timer* pTimer = it->second;
     54   if (pTimer->m_pAttached)
     55     pTimer->m_pAttached->TimerProc();
     56 }
     57 
     58 CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL) {}
     59 
     60 CPWL_TimerHandler::~CPWL_TimerHandler() {
     61   delete m_pTimer;
     62 }
     63 
     64 void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
     65   if (!m_pTimer)
     66     m_pTimer = new CPWL_Timer(this, GetSystemHandler());
     67 
     68   if (m_pTimer)
     69     m_pTimer->SetPWLTimer(nElapse);
     70 }
     71 
     72 void CPWL_TimerHandler::EndTimer() {
     73   if (m_pTimer)
     74     m_pTimer->KillPWLTimer();
     75 }
     76 
     77 void CPWL_TimerHandler::TimerProc() {}
     78 
     79 class CPWL_MsgControl {
     80   friend class CPWL_Wnd;
     81 
     82  public:
     83   explicit CPWL_MsgControl(CPWL_Wnd* pWnd) {
     84     m_pCreatedWnd = pWnd;
     85     Default();
     86   }
     87 
     88   ~CPWL_MsgControl() {
     89     Default();
     90   }
     91 
     92   void Default() {
     93     m_aMousePath.RemoveAll();
     94     m_aKeyboardPath.RemoveAll();
     95     m_pMainMouseWnd = NULL;
     96     m_pMainKeyboardWnd = NULL;
     97   }
     98 
     99   FX_BOOL IsWndCreated(const CPWL_Wnd* pWnd) const {
    100     return m_pCreatedWnd == pWnd;
    101   }
    102 
    103   FX_BOOL IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
    104     return pWnd == m_pMainMouseWnd;
    105   }
    106 
    107   FX_BOOL IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
    108     if (pWnd) {
    109       for (int32_t i = 0, sz = m_aMousePath.GetSize(); i < sz; i++) {
    110         if (m_aMousePath.GetAt(i) == pWnd)
    111           return TRUE;
    112       }
    113     }
    114 
    115     return FALSE;
    116   }
    117 
    118   FX_BOOL IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    119     return pWnd == m_pMainKeyboardWnd;
    120   }
    121 
    122   FX_BOOL IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    123     if (pWnd) {
    124       for (int32_t i = 0, sz = m_aKeyboardPath.GetSize(); i < sz; i++) {
    125         if (m_aKeyboardPath.GetAt(i) == pWnd)
    126           return TRUE;
    127       }
    128     }
    129 
    130     return FALSE;
    131   }
    132 
    133   void SetFocus(CPWL_Wnd* pWnd) {
    134     m_aKeyboardPath.RemoveAll();
    135 
    136     if (pWnd) {
    137       m_pMainKeyboardWnd = pWnd;
    138 
    139       CPWL_Wnd* pParent = pWnd;
    140       while (pParent) {
    141         m_aKeyboardPath.Add(pParent);
    142         pParent = pParent->GetParentWindow();
    143       }
    144 
    145       pWnd->OnSetFocus();
    146     }
    147   }
    148 
    149   void KillFocus() {
    150     if (m_aKeyboardPath.GetSize() > 0)
    151       if (CPWL_Wnd* pWnd = m_aKeyboardPath.GetAt(0))
    152         pWnd->OnKillFocus();
    153 
    154     m_pMainKeyboardWnd = NULL;
    155     m_aKeyboardPath.RemoveAll();
    156   }
    157 
    158   void SetCapture(CPWL_Wnd* pWnd) {
    159     m_aMousePath.RemoveAll();
    160 
    161     if (pWnd) {
    162       m_pMainMouseWnd = pWnd;
    163 
    164       CPWL_Wnd* pParent = pWnd;
    165       while (pParent) {
    166         m_aMousePath.Add(pParent);
    167         pParent = pParent->GetParentWindow();
    168       }
    169     }
    170   }
    171 
    172   void ReleaseCapture() {
    173     m_pMainMouseWnd = NULL;
    174     m_aMousePath.RemoveAll();
    175   }
    176 
    177  private:
    178   CFX_ArrayTemplate<CPWL_Wnd*> m_aMousePath;
    179   CFX_ArrayTemplate<CPWL_Wnd*> m_aKeyboardPath;
    180   CPWL_Wnd* m_pCreatedWnd;
    181   CPWL_Wnd* m_pMainMouseWnd;
    182   CPWL_Wnd* m_pMainKeyboardWnd;
    183 };
    184 
    185 CPWL_Wnd::CPWL_Wnd()
    186     : m_pVScrollBar(NULL),
    187       m_rcWindow(),
    188       m_rcClip(),
    189       m_bCreated(FALSE),
    190       m_bVisible(FALSE),
    191       m_bNotifying(FALSE),
    192       m_bEnabled(TRUE) {}
    193 
    194 CPWL_Wnd::~CPWL_Wnd() {
    195   ASSERT(m_bCreated == FALSE);
    196 }
    197 
    198 CFX_ByteString CPWL_Wnd::GetClassName() const {
    199   return "CPWL_Wnd";
    200 }
    201 
    202 void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) {
    203   if (!IsValid()) {
    204     m_sPrivateParam = cp;
    205 
    206     OnCreate(m_sPrivateParam);
    207 
    208     m_sPrivateParam.rcRectWnd.Normalize();
    209     m_rcWindow = m_sPrivateParam.rcRectWnd;
    210     m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f);
    211 
    212     CreateMsgControl();
    213 
    214     if (m_sPrivateParam.pParentWnd)
    215       m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);
    216 
    217     PWL_CREATEPARAM ccp = m_sPrivateParam;
    218 
    219     ccp.dwFlags &= 0xFFFF0000L;  // remove sub styles
    220     ccp.mtChild = CFX_Matrix(1, 0, 0, 1, 0, 0);
    221 
    222     CreateScrollBar(ccp);
    223     CreateChildWnd(ccp);
    224 
    225     m_bVisible = HasFlag(PWS_VISIBLE);
    226 
    227     OnCreated();
    228 
    229     RePosChildWnd();
    230     m_bCreated = TRUE;
    231   }
    232 }
    233 
    234 void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}
    235 
    236 void CPWL_Wnd::OnCreated() {}
    237 
    238 void CPWL_Wnd::OnDestroy() {}
    239 
    240 void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) {
    241   if (m_sPrivateParam.pFocusHandler == handler)
    242     m_sPrivateParam.pFocusHandler = nullptr;
    243 }
    244 
    245 void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
    246   if (m_sPrivateParam.pProvider == provider)
    247     m_sPrivateParam.pProvider = nullptr;
    248 }
    249 
    250 void CPWL_Wnd::Destroy() {
    251   KillFocus();
    252 
    253   OnDestroy();
    254 
    255   if (m_bCreated) {
    256     for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
    257       if (CPWL_Wnd* pChild = m_aChildren[i]) {
    258         pChild->Destroy();
    259         delete pChild;
    260         pChild = NULL;
    261       }
    262     }
    263 
    264     if (m_sPrivateParam.pParentWnd)
    265       m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
    266     m_bCreated = FALSE;
    267   }
    268 
    269   DestroyMsgControl();
    270 
    271   FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
    272   m_aChildren.RemoveAll();
    273   m_pVScrollBar = NULL;
    274 }
    275 
    276 void CPWL_Wnd::Move(const CPDF_Rect& rcNew, FX_BOOL bReset, FX_BOOL bRefresh) {
    277   if (IsValid()) {
    278     CPDF_Rect rcOld = GetWindowRect();
    279 
    280     m_rcWindow = rcNew;
    281     m_rcWindow.Normalize();
    282 
    283     if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
    284         rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
    285       if (bReset) {
    286         RePosChildWnd();
    287       }
    288     }
    289     if (bRefresh) {
    290       InvalidateRectMove(rcOld, rcNew);
    291     }
    292 
    293     m_sPrivateParam.rcRectWnd = m_rcWindow;
    294   }
    295 }
    296 
    297 void CPWL_Wnd::InvalidateRectMove(const CPDF_Rect& rcOld,
    298                                   const CPDF_Rect& rcNew) {
    299   CPDF_Rect rcUnion = rcOld;
    300   rcUnion.Union(rcNew);
    301 
    302   InvalidateRect(&rcUnion);
    303 }
    304 
    305 void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) {
    306   if (IsValid() && IsVisible()) {
    307     GetThisAppearanceStream(sAppStream);
    308     GetChildAppearanceStream(sAppStream);
    309   }
    310 }
    311 
    312 // if don't set,Get default apperance stream
    313 void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
    314   CPDF_Rect rectWnd = GetWindowRect();
    315   if (!rectWnd.IsEmpty()) {
    316     CFX_ByteTextBuf sThis;
    317 
    318     if (HasFlag(PWS_BACKGROUND))
    319       sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());
    320 
    321     if (HasFlag(PWS_BORDER)) {
    322       sThis << CPWL_Utils::GetBorderAppStream(
    323           rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
    324           GetBorderLeftTopColor(GetBorderStyle()),
    325           GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
    326           GetBorderDash());
    327     }
    328 
    329     sAppStream << sThis;
    330   }
    331 }
    332 
    333 void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) {
    334   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    335     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    336       pChild->GetAppearanceStream(sAppStream);
    337     }
    338   }
    339 }
    340 
    341 void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
    342                               CFX_Matrix* pUser2Device) {
    343   if (IsValid() && IsVisible()) {
    344     DrawThisAppearance(pDevice, pUser2Device);
    345     DrawChildAppearance(pDevice, pUser2Device);
    346   }
    347 }
    348 
    349 void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
    350                                   CFX_Matrix* pUser2Device) {
    351   CPDF_Rect rectWnd = GetWindowRect();
    352   if (!rectWnd.IsEmpty()) {
    353     if (HasFlag(PWS_BACKGROUND)) {
    354       CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
    355           rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
    356       CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
    357                                GetBackgroundColor(), GetTransparency());
    358     }
    359 
    360     if (HasFlag(PWS_BORDER))
    361       CPWL_Utils::DrawBorder(pDevice, pUser2Device, rectWnd,
    362                              (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
    363                              GetBorderLeftTopColor(GetBorderStyle()),
    364                              GetBorderRightBottomColor(GetBorderStyle()),
    365                              GetBorderStyle(), GetTransparency());
    366   }
    367 }
    368 
    369 void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
    370                                    CFX_Matrix* pUser2Device) {
    371   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    372     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    373       CFX_Matrix mt = pChild->GetChildMatrix();
    374       if (mt.IsIdentity()) {
    375         pChild->DrawAppearance(pDevice, pUser2Device);
    376       } else {
    377         mt.Concat(*pUser2Device);
    378         pChild->DrawAppearance(pDevice, &mt);
    379       }
    380     }
    381   }
    382 }
    383 
    384 void CPWL_Wnd::InvalidateRect(CPDF_Rect* pRect) {
    385   if (IsValid()) {
    386     CPDF_Rect rcRefresh = pRect ? *pRect : GetWindowRect();
    387 
    388     if (!HasFlag(PWS_NOREFRESHCLIP)) {
    389       CPDF_Rect rcClip = GetClipRect();
    390       if (!rcClip.IsEmpty()) {
    391         rcRefresh.Intersect(rcClip);
    392       }
    393     }
    394 
    395     FX_RECT rcWin = PWLtoWnd(rcRefresh);
    396     rcWin.left -= PWL_INVALIDATE_INFLATE;
    397     rcWin.top -= PWL_INVALIDATE_INFLATE;
    398     rcWin.right += PWL_INVALIDATE_INFLATE;
    399     rcWin.bottom += PWL_INVALIDATE_INFLATE;
    400 
    401     if (IFX_SystemHandler* pSH = GetSystemHandler()) {
    402       if (FX_HWND hWnd = GetAttachedHWnd()) {
    403         pSH->InvalidateRect(hWnd, rcWin);
    404       }
    405     }
    406   }
    407 }
    408 
    409 #define PWL_IMPLEMENT_KEY_METHOD(key_method_name)                      \
    410   FX_BOOL CPWL_Wnd::key_method_name(FX_WORD nChar, FX_DWORD nFlag) {   \
    411     if (IsValid() && IsVisible() && IsEnabled()) {                     \
    412       if (IsWndCaptureKeyboard(this)) {                                \
    413         for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) { \
    414           if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {               \
    415             if (IsWndCaptureKeyboard(pChild)) {                        \
    416               return pChild->key_method_name(nChar, nFlag);            \
    417             }                                                          \
    418           }                                                            \
    419         }                                                              \
    420       }                                                                \
    421     }                                                                  \
    422     return FALSE;                                                      \
    423   }
    424 
    425 #define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)                        \
    426   FX_BOOL CPWL_Wnd::mouse_method_name(const CPDF_Point& point,               \
    427                                       FX_DWORD nFlag) {                      \
    428     if (IsValid() && IsVisible() && IsEnabled()) {                           \
    429       if (IsWndCaptureMouse(this)) {                                         \
    430         for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
    431           if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
    432             if (IsWndCaptureMouse(pChild)) {                                 \
    433               return pChild->mouse_method_name(pChild->ParentToChild(point), \
    434                                                nFlag);                       \
    435             }                                                                \
    436           }                                                                  \
    437         }                                                                    \
    438         SetCursor();                                                         \
    439       } else {                                                               \
    440         for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
    441           if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
    442             if (pChild->WndHitTest(pChild->ParentToChild(point))) {          \
    443               return pChild->mouse_method_name(pChild->ParentToChild(point), \
    444                                                nFlag);                       \
    445             }                                                                \
    446           }                                                                  \
    447         }                                                                    \
    448         if (WndHitTest(point))                                               \
    449           SetCursor();                                                       \
    450       }                                                                      \
    451     }                                                                        \
    452     return FALSE;                                                            \
    453   }
    454 
    455 PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
    456 PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)
    457 PWL_IMPLEMENT_KEY_METHOD(OnChar)
    458 
    459 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
    460 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
    461 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
    462 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDblClk)
    463 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDown)
    464 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonUp)
    465 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
    466 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
    467 PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
    468 
    469 FX_BOOL CPWL_Wnd::OnMouseWheel(short zDelta,
    470                                const CPDF_Point& point,
    471                                FX_DWORD nFlag) {
    472   if (IsValid() && IsVisible() && IsEnabled()) {
    473     SetCursor();
    474     if (IsWndCaptureKeyboard(this)) {
    475       for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    476         if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    477           if (IsWndCaptureKeyboard(pChild)) {
    478             return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point),
    479                                         nFlag);
    480           }
    481         }
    482       }
    483     }
    484   }
    485   return FALSE;
    486 }
    487 
    488 void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
    489   m_aChildren.Add(pWnd);
    490 }
    491 
    492 void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
    493   for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
    494     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    495       if (pChild == pWnd) {
    496         m_aChildren.RemoveAt(i);
    497         break;
    498       }
    499     }
    500   }
    501 }
    502 
    503 void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd,
    504                         FX_DWORD msg,
    505                         intptr_t wParam,
    506                         intptr_t lParam) {
    507   switch (msg) {
    508     case PNM_ADDCHILD:
    509       AddChild(pWnd);
    510       break;
    511     case PNM_REMOVECHILD:
    512       RemoveChild(pWnd);
    513       break;
    514     default:
    515       break;
    516   }
    517 }
    518 
    519 FX_BOOL CPWL_Wnd::IsValid() const {
    520   return m_bCreated;
    521 }
    522 
    523 const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const {
    524   return m_sPrivateParam;
    525 }
    526 
    527 CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
    528   return m_sPrivateParam.pParentWnd;
    529 }
    530 
    531 CPDF_Rect CPWL_Wnd::GetWindowRect() const {
    532   return m_rcWindow;
    533 }
    534 
    535 CPDF_Rect CPWL_Wnd::GetClientRect() const {
    536   CPDF_Rect rcWindow = GetWindowRect();
    537   CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
    538       rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
    539   if (CPWL_ScrollBar* pVSB = GetVScrollBar())
    540     rcClient.right -= pVSB->GetScrollBarWidth();
    541 
    542   rcClient.Normalize();
    543   return rcWindow.Contains(rcClient) ? rcClient : CPDF_Rect();
    544 }
    545 
    546 CPDF_Point CPWL_Wnd::GetCenterPoint() const {
    547   CPDF_Rect rcClient = GetClientRect();
    548   return CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
    549                     (rcClient.top + rcClient.bottom) * 0.5f);
    550 }
    551 
    552 FX_BOOL CPWL_Wnd::HasFlag(FX_DWORD dwFlags) const {
    553   return (m_sPrivateParam.dwFlags & dwFlags) != 0;
    554 }
    555 
    556 void CPWL_Wnd::RemoveFlag(FX_DWORD dwFlags) {
    557   m_sPrivateParam.dwFlags &= ~dwFlags;
    558 }
    559 
    560 void CPWL_Wnd::AddFlag(FX_DWORD dwFlags) {
    561   m_sPrivateParam.dwFlags |= dwFlags;
    562 }
    563 
    564 CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
    565   return m_sPrivateParam.sBackgroundColor;
    566 }
    567 
    568 void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
    569   m_sPrivateParam.sBackgroundColor = color;
    570 }
    571 
    572 void CPWL_Wnd::SetTextColor(const CPWL_Color& color) {
    573   m_sPrivateParam.sTextColor = color;
    574 }
    575 
    576 void CPWL_Wnd::SetTextStrokeColor(const CPWL_Color& color) {
    577   m_sPrivateParam.sTextStrokeColor = color;
    578 }
    579 
    580 CPWL_Color CPWL_Wnd::GetTextColor() const {
    581   return m_sPrivateParam.sTextColor;
    582 }
    583 
    584 CPWL_Color CPWL_Wnd::GetTextStrokeColor() const {
    585   return m_sPrivateParam.sTextStrokeColor;
    586 }
    587 
    588 int32_t CPWL_Wnd::GetBorderStyle() const {
    589   return m_sPrivateParam.nBorderStyle;
    590 }
    591 
    592 void CPWL_Wnd::SetBorderStyle(int32_t nBorderStyle) {
    593   if (HasFlag(PWS_BORDER))
    594     m_sPrivateParam.nBorderStyle = nBorderStyle;
    595 }
    596 
    597 int32_t CPWL_Wnd::GetBorderWidth() const {
    598   if (HasFlag(PWS_BORDER))
    599     return m_sPrivateParam.dwBorderWidth;
    600 
    601   return 0;
    602 }
    603 
    604 int32_t CPWL_Wnd::GetInnerBorderWidth() const {
    605   return 0;
    606 }
    607 
    608 CPWL_Color CPWL_Wnd::GetBorderColor() const {
    609   if (HasFlag(PWS_BORDER))
    610     return m_sPrivateParam.sBorderColor;
    611 
    612   return CPWL_Color();
    613 }
    614 
    615 const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
    616   return m_sPrivateParam.sDash;
    617 }
    618 
    619 void* CPWL_Wnd::GetAttachedData() const {
    620   return m_sPrivateParam.pAttachedData;
    621 }
    622 
    623 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
    624   if (HasFlag(PWS_VSCROLL))
    625     return m_pVScrollBar;
    626 
    627   return NULL;
    628 }
    629 
    630 void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
    631   CreateVScrollBar(cp);
    632 }
    633 
    634 void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) {
    635   if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) {
    636     PWL_CREATEPARAM scp = cp;
    637 
    638     // flags
    639     scp.dwFlags =
    640         PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
    641 
    642     scp.pParentWnd = this;
    643     scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
    644     scp.eCursorType = FXCT_ARROW;
    645     scp.nTransparency = PWL_SCROLLBAR_TRANSPARANCY;
    646 
    647     m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
    648     m_pVScrollBar->Create(scp);
    649   }
    650 }
    651 
    652 void CPWL_Wnd::SetCapture() {
    653   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
    654     pMsgCtrl->SetCapture(this);
    655 }
    656 
    657 void CPWL_Wnd::ReleaseCapture() {
    658   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++)
    659     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
    660       pChild->ReleaseCapture();
    661 
    662   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
    663     pMsgCtrl->ReleaseCapture();
    664 }
    665 
    666 void CPWL_Wnd::SetFocus() {
    667   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    668     if (!pMsgCtrl->IsMainCaptureKeyboard(this))
    669       pMsgCtrl->KillFocus();
    670     pMsgCtrl->SetFocus(this);
    671   }
    672 }
    673 
    674 void CPWL_Wnd::KillFocus() {
    675   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    676     if (pMsgCtrl->IsWndCaptureKeyboard(this))
    677       pMsgCtrl->KillFocus();
    678   }
    679 }
    680 
    681 void CPWL_Wnd::OnSetFocus() {}
    682 
    683 void CPWL_Wnd::OnKillFocus() {}
    684 
    685 FX_BOOL CPWL_Wnd::WndHitTest(const CPDF_Point& point) const {
    686   return IsValid() && IsVisible() && GetWindowRect().Contains(point.x, point.y);
    687 }
    688 
    689 FX_BOOL CPWL_Wnd::ClientHitTest(const CPDF_Point& point) const {
    690   return IsValid() && IsVisible() && GetClientRect().Contains(point.x, point.y);
    691 }
    692 
    693 const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
    694   if (m_sPrivateParam.pParentWnd)
    695     return m_sPrivateParam.pParentWnd->GetRootWnd();
    696 
    697   return this;
    698 }
    699 
    700 void CPWL_Wnd::SetVisible(FX_BOOL bVisible) {
    701   if (IsValid()) {
    702     for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    703       if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    704         pChild->SetVisible(bVisible);
    705       }
    706     }
    707 
    708     if (bVisible != m_bVisible) {
    709       m_bVisible = bVisible;
    710       RePosChildWnd();
    711       InvalidateRect();
    712     }
    713   }
    714 }
    715 
    716 void CPWL_Wnd::SetClipRect(const CPDF_Rect& rect) {
    717   m_rcClip = rect;
    718   m_rcClip.Normalize();
    719 }
    720 
    721 const CPDF_Rect& CPWL_Wnd::GetClipRect() const {
    722   return m_rcClip;
    723 }
    724 
    725 FX_BOOL CPWL_Wnd::IsReadOnly() const {
    726   return HasFlag(PWS_READONLY);
    727 }
    728 
    729 void CPWL_Wnd::RePosChildWnd() {
    730   CPDF_Rect rcContent = CPWL_Utils::DeflateRect(
    731       GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
    732 
    733   CPWL_ScrollBar* pVSB = GetVScrollBar();
    734 
    735   CPDF_Rect rcVScroll =
    736       CPDF_Rect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
    737                 rcContent.right - 1.0f, rcContent.top);
    738 
    739   if (pVSB)
    740     pVSB->Move(rcVScroll, TRUE, FALSE);
    741 }
    742 
    743 void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}
    744 
    745 void CPWL_Wnd::SetCursor() {
    746   if (IsValid()) {
    747     if (IFX_SystemHandler* pSH = GetSystemHandler()) {
    748       int32_t nCursorType = GetCreationParam().eCursorType;
    749       pSH->SetCursor(nCursorType);
    750     }
    751   }
    752 }
    753 
    754 void CPWL_Wnd::CreateMsgControl() {
    755   if (!m_sPrivateParam.pMsgControl)
    756     m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
    757 }
    758 
    759 void CPWL_Wnd::DestroyMsgControl() {
    760   if (CPWL_MsgControl* pMsgControl = GetMsgControl())
    761     if (pMsgControl->IsWndCreated(this))
    762       delete pMsgControl;
    763 }
    764 
    765 CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
    766   return m_sPrivateParam.pMsgControl;
    767 }
    768 
    769 FX_BOOL CPWL_Wnd::IsCaptureMouse() const {
    770   return IsWndCaptureMouse(this);
    771 }
    772 
    773 FX_BOOL CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
    774   if (CPWL_MsgControl* pCtrl = GetMsgControl())
    775     return pCtrl->IsWndCaptureMouse(pWnd);
    776 
    777   return FALSE;
    778 }
    779 
    780 FX_BOOL CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    781   if (CPWL_MsgControl* pCtrl = GetMsgControl())
    782     return pCtrl->IsWndCaptureKeyboard(pWnd);
    783 
    784   return FALSE;
    785 }
    786 
    787 FX_BOOL CPWL_Wnd::IsFocused() const {
    788   if (CPWL_MsgControl* pCtrl = GetMsgControl())
    789     return pCtrl->IsMainCaptureKeyboard(this);
    790 
    791   return FALSE;
    792 }
    793 
    794 CPDF_Rect CPWL_Wnd::GetFocusRect() const {
    795   return CPWL_Utils::InflateRect(GetWindowRect(), 1);
    796 }
    797 
    798 FX_FLOAT CPWL_Wnd::GetFontSize() const {
    799   return m_sPrivateParam.fFontSize;
    800 }
    801 
    802 void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
    803   m_sPrivateParam.fFontSize = fFontSize;
    804 }
    805 
    806 IFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
    807   return m_sPrivateParam.pSystemHandler;
    808 }
    809 
    810 IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
    811   return m_sPrivateParam.pFocusHandler;
    812 }
    813 
    814 IPWL_Provider* CPWL_Wnd::GetProvider() const {
    815   return m_sPrivateParam.pProvider;
    816 }
    817 
    818 IFX_Edit_FontMap* CPWL_Wnd::GetFontMap() const {
    819   return m_sPrivateParam.pFontMap;
    820 }
    821 
    822 CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(int32_t nBorderStyle) const {
    823   CPWL_Color color;
    824 
    825   switch (nBorderStyle) {
    826     case PBS_SOLID:
    827       break;
    828     case PBS_DASH:
    829       break;
    830     case PBS_BEVELED:
    831       color = CPWL_Color(COLORTYPE_GRAY, 1);
    832       break;
    833     case PBS_INSET:
    834       color = CPWL_Color(COLORTYPE_GRAY, 0.5f);
    835       break;
    836     case PBS_UNDERLINED:
    837       break;
    838   }
    839 
    840   return color;
    841 }
    842 
    843 CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(int32_t nBorderStyle) const {
    844   CPWL_Color color;
    845 
    846   switch (nBorderStyle) {
    847     case PBS_SOLID:
    848       break;
    849     case PBS_DASH:
    850       break;
    851     case PBS_BEVELED:
    852       color = CPWL_Utils::DevideColor(GetBackgroundColor(), 2);
    853       break;
    854     case PBS_INSET:
    855       color = CPWL_Color(COLORTYPE_GRAY, 0.75f);
    856       break;
    857     case PBS_UNDERLINED:
    858       break;
    859   }
    860 
    861   return color;
    862 }
    863 
    864 int32_t CPWL_Wnd::GetTransparency() {
    865   return m_sPrivateParam.nTransparency;
    866 }
    867 
    868 void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
    869   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    870     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    871       pChild->SetTransparency(nTransparency);
    872     }
    873   }
    874 
    875   m_sPrivateParam.nTransparency = nTransparency;
    876 }
    877 
    878 CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
    879   CFX_Matrix mt = GetChildToRoot();
    880 
    881   if (IPWL_Provider* pProvider = GetProvider()) {
    882     mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
    883     return mt;
    884   }
    885 
    886   return mt;
    887 }
    888 
    889 void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, int32_t& x, int32_t& y) const {
    890   CFX_Matrix mt = GetWindowMatrix();
    891   CPDF_Point pt = point;
    892   mt.Transform(pt.x, pt.y);
    893   x = (int32_t)(pt.x + 0.5);
    894   y = (int32_t)(pt.y + 0.5);
    895 }
    896 
    897 FX_RECT CPWL_Wnd::PWLtoWnd(const CPDF_Rect& rect) const {
    898   CPDF_Rect rcTemp = rect;
    899   CFX_Matrix mt = GetWindowMatrix();
    900   mt.TransformRect(rcTemp);
    901   return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
    902                  (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
    903 }
    904 
    905 FX_HWND CPWL_Wnd::GetAttachedHWnd() const {
    906   return m_sPrivateParam.hAttachedWnd;
    907 }
    908 
    909 CPDF_Point CPWL_Wnd::ChildToParent(const CPDF_Point& point) const {
    910   CFX_Matrix mt = GetChildMatrix();
    911   if (mt.IsIdentity())
    912     return point;
    913 
    914   CPDF_Point pt = point;
    915   mt.Transform(pt.x, pt.y);
    916   return pt;
    917 }
    918 
    919 CPDF_Rect CPWL_Wnd::ChildToParent(const CPDF_Rect& rect) const {
    920   CFX_Matrix mt = GetChildMatrix();
    921   if (mt.IsIdentity())
    922     return rect;
    923 
    924   CPDF_Rect rc = rect;
    925   mt.TransformRect(rc);
    926   return rc;
    927 }
    928 
    929 CPDF_Point CPWL_Wnd::ParentToChild(const CPDF_Point& point) const {
    930   CFX_Matrix mt = GetChildMatrix();
    931   if (mt.IsIdentity())
    932     return point;
    933 
    934   mt.SetReverse(mt);
    935   CPDF_Point pt = point;
    936   mt.Transform(pt.x, pt.y);
    937   return pt;
    938 }
    939 
    940 CPDF_Rect CPWL_Wnd::ParentToChild(const CPDF_Rect& rect) const {
    941   CFX_Matrix mt = GetChildMatrix();
    942   if (mt.IsIdentity())
    943     return rect;
    944 
    945   mt.SetReverse(mt);
    946   CPDF_Rect rc = rect;
    947   mt.TransformRect(rc);
    948   return rc;
    949 }
    950 
    951 CFX_Matrix CPWL_Wnd::GetChildToRoot() const {
    952   CFX_Matrix mt(1, 0, 0, 1, 0, 0);
    953   if (HasFlag(PWS_CHILD)) {
    954     const CPWL_Wnd* pParent = this;
    955     while (pParent) {
    956       mt.Concat(pParent->GetChildMatrix());
    957       pParent = pParent->GetParentWindow();
    958     }
    959   }
    960   return mt;
    961 }
    962 
    963 CFX_Matrix CPWL_Wnd::GetChildMatrix() const {
    964   if (HasFlag(PWS_CHILD))
    965     return m_sPrivateParam.mtChild;
    966 
    967   return CFX_Matrix(1, 0, 0, 1, 0, 0);
    968 }
    969 
    970 void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
    971   m_sPrivateParam.mtChild = mt;
    972 }
    973 
    974 const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
    975   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    976     return pMsgCtrl->m_pMainKeyboardWnd;
    977   }
    978 
    979   return NULL;
    980 }
    981 
    982 void CPWL_Wnd::EnableWindow(FX_BOOL bEnable) {
    983   if (m_bEnabled != bEnable) {
    984     for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    985       if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    986         pChild->EnableWindow(bEnable);
    987       }
    988     }
    989 
    990     m_bEnabled = bEnable;
    991 
    992     if (bEnable)
    993       OnEnabled();
    994     else
    995       OnDisabled();
    996   }
    997 }
    998 
    999 FX_BOOL CPWL_Wnd::IsEnabled() {
   1000   return m_bEnabled;
   1001 }
   1002 
   1003 void CPWL_Wnd::OnEnabled() {}
   1004 
   1005 void CPWL_Wnd::OnDisabled() {}
   1006 
   1007 FX_BOOL CPWL_Wnd::IsCTRLpressed(FX_DWORD nFlag) const {
   1008   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
   1009     return pSystemHandler->IsCTRLKeyDown(nFlag);
   1010   }
   1011 
   1012   return FALSE;
   1013 }
   1014 
   1015 FX_BOOL CPWL_Wnd::IsSHIFTpressed(FX_DWORD nFlag) const {
   1016   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
   1017     return pSystemHandler->IsSHIFTKeyDown(nFlag);
   1018   }
   1019 
   1020   return FALSE;
   1021 }
   1022 
   1023 FX_BOOL CPWL_Wnd::IsALTpressed(FX_DWORD nFlag) const {
   1024   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
   1025     return pSystemHandler->IsALTKeyDown(nFlag);
   1026   }
   1027 
   1028   return FALSE;
   1029 }
   1030 
   1031 FX_BOOL CPWL_Wnd::IsINSERTpressed(FX_DWORD nFlag) const {
   1032   if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
   1033     return pSystemHandler->IsINSERTKeyDown(nFlag);
   1034   }
   1035 
   1036   return FALSE;
   1037 }
   1038