• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetPWLTimeMap()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 
PWL_CREATEPARAM()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 
CPWL_Timer(CPWL_TimerHandler * pAttached,CFX_SystemHandler * pSystemHandler)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 
~CPWL_Timer()53 CPWL_Timer::~CPWL_Timer() {
54   KillPWLTimer();
55 }
56 
SetPWLTimer(int32_t nElapse)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 
KillPWLTimer()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 
TimerProc(int32_t idEvent)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 
CPWL_TimerHandler()85 CPWL_TimerHandler::CPWL_TimerHandler() {}
86 
~CPWL_TimerHandler()87 CPWL_TimerHandler::~CPWL_TimerHandler() {}
88 
BeginTimer(int32_t nElapse)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 
EndTimer()96 void CPWL_TimerHandler::EndTimer() {
97   if (m_pTimer)
98     m_pTimer->KillPWLTimer();
99 }
100 
TimerProc()101 void CPWL_TimerHandler::TimerProc() {}
102 
103 class CPWL_MsgControl {
104   friend class CPWL_Wnd;
105 
106  public:
CPWL_MsgControl(CPWL_Wnd * pWnd)107   explicit CPWL_MsgControl(CPWL_Wnd* pWnd) {
108     m_pCreatedWnd = pWnd;
109     Default();
110   }
111 
~CPWL_MsgControl()112   ~CPWL_MsgControl() { Default(); }
113 
Default()114   void Default() {
115     m_aMousePath.clear();
116     m_aKeyboardPath.clear();
117     m_pMainMouseWnd = nullptr;
118     m_pMainKeyboardWnd = nullptr;
119   }
120 
IsWndCreated(const CPWL_Wnd * pWnd) const121   bool IsWndCreated(const CPWL_Wnd* pWnd) const {
122     return m_pCreatedWnd == pWnd;
123   }
124 
IsMainCaptureMouse(const CPWL_Wnd * pWnd) const125   bool IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
126     return pWnd == m_pMainMouseWnd;
127   }
128 
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const129   bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
130     return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd);
131   }
132 
IsMainCaptureKeyboard(const CPWL_Wnd * pWnd) const133   bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
134     return pWnd == m_pMainKeyboardWnd;
135   }
136 
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const137   bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
138     return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd);
139   }
140 
SetFocus(CPWL_Wnd * pWnd)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 
KillFocus()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 
SetCapture(CPWL_Wnd * pWnd)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 
ReleaseCapture()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 
CPWL_Wnd()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 
~CPWL_Wnd()197 CPWL_Wnd::~CPWL_Wnd() {
198   ASSERT(m_bCreated == false);
199 }
200 
GetClassName() const201 CFX_ByteString CPWL_Wnd::GetClassName() const {
202   return "CPWL_Wnd";
203 }
204 
Create(const PWL_CREATEPARAM & cp)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 
OnCreate(PWL_CREATEPARAM & cp)237 void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}
238 
OnCreated()239 void CPWL_Wnd::OnCreated() {}
240 
OnDestroy()241 void CPWL_Wnd::OnDestroy() {}
242 
InvalidateFocusHandler(IPWL_FocusHandler * handler)243 void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) {
244   if (m_sPrivateParam.pFocusHandler == handler)
245     m_sPrivateParam.pFocusHandler = nullptr;
246 }
247 
InvalidateProvider(IPWL_Provider * provider)248 void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
249   if (m_sPrivateParam.pProvider.Get() == provider)
250     m_sPrivateParam.pProvider.Reset();
251 }
252 
Destroy()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 
Move(const CFX_FloatRect & rcNew,bool bReset,bool bRefresh)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 
InvalidateRectMove(const CFX_FloatRect & rcOld,const CFX_FloatRect & rcNew)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 
GetAppearanceStream(CFX_ByteTextBuf & sAppStream)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
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)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 
GetChildAppearanceStream(CFX_ByteTextBuf & sAppStream)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 
DrawAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
DrawChildAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
InvalidateRect(CFX_FloatRect * pRect)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)
PWL_IMPLEMENT_KEY_METHOD(OnChar)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 
AddChild(CPWL_Wnd * pWnd)475 void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
476   m_Children.push_back(pWnd);
477 }
478 
RemoveChild(CPWL_Wnd * pWnd)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 
OnNotify(CPWL_Wnd * pWnd,uint32_t msg,intptr_t wParam,intptr_t lParam)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 
IsValid() const504 bool CPWL_Wnd::IsValid() const {
505   return m_bCreated;
506 }
507 
GetCreationParam() const508 const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const {
509   return m_sPrivateParam;
510 }
511 
GetParentWindow() const512 CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
513   return m_sPrivateParam.pParentWnd;
514 }
515 
GetWindowRect() const516 CFX_FloatRect CPWL_Wnd::GetWindowRect() const {
517   return m_rcWindow;
518 }
519 
GetClientRect() const520 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 
GetCenterPoint() const531 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 
HasFlag(uint32_t dwFlags) const537 bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const {
538   return (m_sPrivateParam.dwFlags & dwFlags) != 0;
539 }
540 
RemoveFlag(uint32_t dwFlags)541 void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) {
542   m_sPrivateParam.dwFlags &= ~dwFlags;
543 }
544 
AddFlag(uint32_t dwFlags)545 void CPWL_Wnd::AddFlag(uint32_t dwFlags) {
546   m_sPrivateParam.dwFlags |= dwFlags;
547 }
548 
GetBackgroundColor() const549 CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
550   return m_sPrivateParam.sBackgroundColor;
551 }
552 
SetBackgroundColor(const CPWL_Color & color)553 void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
554   m_sPrivateParam.sBackgroundColor = color;
555 }
556 
GetTextColor() const557 CPWL_Color CPWL_Wnd::GetTextColor() const {
558   return m_sPrivateParam.sTextColor;
559 }
560 
GetBorderStyle() const561 BorderStyle CPWL_Wnd::GetBorderStyle() const {
562   return m_sPrivateParam.nBorderStyle;
563 }
564 
SetBorderStyle(BorderStyle nBorderStyle)565 void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) {
566   if (HasFlag(PWS_BORDER))
567     m_sPrivateParam.nBorderStyle = nBorderStyle;
568 }
569 
GetBorderWidth() const570 int32_t CPWL_Wnd::GetBorderWidth() const {
571   if (HasFlag(PWS_BORDER))
572     return m_sPrivateParam.dwBorderWidth;
573 
574   return 0;
575 }
576 
GetInnerBorderWidth() const577 int32_t CPWL_Wnd::GetInnerBorderWidth() const {
578   return 0;
579 }
580 
GetBorderColor() const581 CPWL_Color CPWL_Wnd::GetBorderColor() const {
582   if (HasFlag(PWS_BORDER))
583     return m_sPrivateParam.sBorderColor;
584 
585   return CPWL_Color();
586 }
587 
GetBorderDash() const588 const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
589   return m_sPrivateParam.sDash;
590 }
591 
GetAttachedData() const592 void* CPWL_Wnd::GetAttachedData() const {
593   return m_sPrivateParam.pAttachedData;
594 }
595 
GetVScrollBar() const596 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
597   if (HasFlag(PWS_VSCROLL))
598     return m_pVScrollBar;
599 
600   return nullptr;
601 }
602 
CreateScrollBar(const PWL_CREATEPARAM & cp)603 void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
604   CreateVScrollBar(cp);
605 }
606 
CreateVScrollBar(const PWL_CREATEPARAM & cp)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 
SetCapture()625 void CPWL_Wnd::SetCapture() {
626   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
627     pMsgCtrl->SetCapture(this);
628 }
629 
ReleaseCapture()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 
SetFocus()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 
KillFocus()647 void CPWL_Wnd::KillFocus() {
648   if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
649     if (pMsgCtrl->IsWndCaptureKeyboard(this))
650       pMsgCtrl->KillFocus();
651   }
652 }
653 
OnSetFocus()654 void CPWL_Wnd::OnSetFocus() {}
655 
OnKillFocus()656 void CPWL_Wnd::OnKillFocus() {}
657 
WndHitTest(const CFX_PointF & point) const658 bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const {
659   return IsValid() && IsVisible() && GetWindowRect().Contains(point);
660 }
661 
ClientHitTest(const CFX_PointF & point) const662 bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const {
663   return IsValid() && IsVisible() && GetClientRect().Contains(point);
664 }
665 
GetRootWnd() const666 const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
667   if (m_sPrivateParam.pParentWnd)
668     return m_sPrivateParam.pParentWnd->GetRootWnd();
669 
670   return this;
671 }
672 
SetVisible(bool bVisible)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 
SetClipRect(const CFX_FloatRect & rect)688 void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) {
689   m_rcClip = rect;
690   m_rcClip.Normalize();
691 }
692 
GetClipRect() const693 const CFX_FloatRect& CPWL_Wnd::GetClipRect() const {
694   return m_rcClip;
695 }
696 
IsReadOnly() const697 bool CPWL_Wnd::IsReadOnly() const {
698   return HasFlag(PWS_READONLY);
699 }
700 
RePosChildWnd()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 
CreateChildWnd(const PWL_CREATEPARAM & cp)715 void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}
716 
SetCursor()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 
CreateMsgControl()726 void CPWL_Wnd::CreateMsgControl() {
727   if (!m_sPrivateParam.pMsgControl)
728     m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
729 }
730 
DestroyMsgControl()731 void CPWL_Wnd::DestroyMsgControl() {
732   if (CPWL_MsgControl* pMsgControl = GetMsgControl())
733     if (pMsgControl->IsWndCreated(this))
734       delete pMsgControl;
735 }
736 
GetMsgControl() const737 CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
738   return m_sPrivateParam.pMsgControl;
739 }
740 
IsCaptureMouse() const741 bool CPWL_Wnd::IsCaptureMouse() const {
742   return IsWndCaptureMouse(this);
743 }
744 
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const745 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 
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const752 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 
IsFocused() const759 bool CPWL_Wnd::IsFocused() const {
760   if (CPWL_MsgControl* pCtrl = GetMsgControl())
761     return pCtrl->IsMainCaptureKeyboard(this);
762 
763   return false;
764 }
765 
GetFocusRect() const766 CFX_FloatRect CPWL_Wnd::GetFocusRect() const {
767   return CPWL_Utils::InflateRect(GetWindowRect(), 1);
768 }
769 
GetFontSize() const770 FX_FLOAT CPWL_Wnd::GetFontSize() const {
771   return m_sPrivateParam.fFontSize;
772 }
773 
SetFontSize(FX_FLOAT fFontSize)774 void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
775   m_sPrivateParam.fFontSize = fFontSize;
776 }
777 
GetSystemHandler() const778 CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
779   return m_sPrivateParam.pSystemHandler;
780 }
781 
GetFocusHandler() const782 IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
783   return m_sPrivateParam.pFocusHandler;
784 }
785 
GetProvider() const786 IPWL_Provider* CPWL_Wnd::GetProvider() const {
787   return m_sPrivateParam.pProvider.Get();
788 }
789 
GetFontMap() const790 IPVT_FontMap* CPWL_Wnd::GetFontMap() const {
791   return m_sPrivateParam.pFontMap;
792 }
793 
GetBorderLeftTopColor(BorderStyle nBorderStyle) const794 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 
GetBorderRightBottomColor(BorderStyle nBorderStyle) const805 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 
GetTransparency()816 int32_t CPWL_Wnd::GetTransparency() {
817   return m_sPrivateParam.nTransparency;
818 }
819 
SetTransparency(int32_t nTransparency)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 
GetWindowMatrix() const828 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 
PWLtoWnd(const CFX_FloatRect & rect) const835 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 
ParentToChild(const CFX_PointF & point) const843 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 
ParentToChild(const CFX_FloatRect & rect) const852 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 
GetChildToRoot() const863 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 
GetChildMatrix() const875 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 
SetChildMatrix(const CFX_Matrix & mt)882 void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
883   m_sPrivateParam.mtChild = mt;
884 }
885 
GetFocused() const886 const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
887   CPWL_MsgControl* pMsgCtrl = GetMsgControl();
888   return pMsgCtrl ? pMsgCtrl->m_pMainKeyboardWnd : nullptr;
889 }
890 
EnableWindow(bool bEnable)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 
IsCTRLpressed(uint32_t nFlag) const902 bool CPWL_Wnd::IsCTRLpressed(uint32_t nFlag) const {
903   CFX_SystemHandler* pSystemHandler = GetSystemHandler();
904   return pSystemHandler && pSystemHandler->IsCTRLKeyDown(nFlag);
905 }
906 
IsSHIFTpressed(uint32_t nFlag) const907 bool CPWL_Wnd::IsSHIFTpressed(uint32_t nFlag) const {
908   CFX_SystemHandler* pSystemHandler = GetSystemHandler();
909   return pSystemHandler && pSystemHandler->IsSHIFTKeyDown(nFlag);
910 }
911 
IsALTpressed(uint32_t nFlag) const912 bool CPWL_Wnd::IsALTpressed(uint32_t nFlag) const {
913   CFX_SystemHandler* pSystemHandler = GetSystemHandler();
914   return pSystemHandler && pSystemHandler->IsALTKeyDown(nFlag);
915 }
916