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