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