| // Copyright 2021 The PDFium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "fpdfsdk/pwl/cpwl_sbbutton.h" | |
| #include <utility> | |
| #include <vector> | |
| #include "core/fxge/cfx_renderdevice.h" | |
| CPWL_SBButton::CPWL_SBButton( | |
| const CreateParams& cp, | |
| std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData, | |
| Type eButtonType) | |
| : CPWL_Wnd(cp, std::move(pAttachedData)), m_eSBButtonType(eButtonType) { | |
| GetCreationParams()->eCursorType = IPWL_FillerNotify::CursorStyle::kArrow; | |
| } | |
| CPWL_SBButton::~CPWL_SBButton() = default; | |
| void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, | |
| const CFX_Matrix& mtUser2Device) { | |
| if (!IsVisible()) | |
| return; | |
| CFX_FloatRect rectWnd = GetWindowRect(); | |
| if (rectWnd.IsEmpty()) | |
| return; | |
| CFX_PointF ptCenter = GetCenterPoint(); | |
| int32_t nTransparency = GetTransparency(); | |
| // draw border | |
| pDevice->DrawStrokeRect(mtUser2Device, rectWnd, | |
| ArgbEncode(nTransparency, 100, 100, 100), 0.0f); | |
| pDevice->DrawStrokeRect(mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f), | |
| ArgbEncode(nTransparency, 255, 255, 255), 1.0f); | |
| if (m_eSBButtonType != Type::kPosButton) { | |
| // draw background | |
| pDevice->DrawShadow(mtUser2Device, rectWnd.GetDeflated(1.0f, 1.0f), | |
| nTransparency, 80, 220); | |
| // draw arrow | |
| if (rectWnd.top - rectWnd.bottom > 6.0f) { | |
| float fX = rectWnd.left + 1.5f; | |
| float fY = rectWnd.bottom; | |
| std::vector<CFX_PointF> pts; | |
| static constexpr float kOffsetsX[] = {2.5f, 2.5f, 4.5f, 6.5f, | |
| 6.5f, 4.5f, 2.5f}; | |
| static constexpr float kOffsetsY[] = {5.0f, 6.0f, 4.0f, 6.0f, | |
| 5.0f, 3.0f, 5.0f}; | |
| static constexpr float kOffsetsMinY[] = {4.0f, 3.0f, 5.0f, 3.0f, | |
| 4.0f, 6.0f, 4.0f}; | |
| static_assert(std::size(kOffsetsX) == std::size(kOffsetsY), | |
| "Wrong offset count"); | |
| static_assert(std::size(kOffsetsX) == std::size(kOffsetsMinY), | |
| "Wrong offset count"); | |
| const float* pOffsetsY = | |
| m_eSBButtonType == Type::kMinButton ? kOffsetsMinY : kOffsetsY; | |
| for (size_t i = 0; i < std::size(kOffsetsX); ++i) | |
| pts.push_back(CFX_PointF(fX + kOffsetsX[i], fY + pOffsetsY[i])); | |
| pDevice->DrawFillArea(mtUser2Device, pts, | |
| ArgbEncode(nTransparency, 255, 255, 255)); | |
| } | |
| return; | |
| } | |
| // draw shadow effect | |
| CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f); | |
| CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f); | |
| ptTop.x += 1.5f; | |
| ptBottom.x += 1.5f; | |
| const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210), | |
| ArgbEncode(nTransparency, 220, 220, 220), | |
| ArgbEncode(nTransparency, 240, 240, 240), | |
| ArgbEncode(nTransparency, 240, 240, 240), | |
| ArgbEncode(nTransparency, 210, 210, 210), | |
| ArgbEncode(nTransparency, 180, 180, 180), | |
| ArgbEncode(nTransparency, 150, 150, 150), | |
| ArgbEncode(nTransparency, 150, 150, 150), | |
| ArgbEncode(nTransparency, 180, 180, 180), | |
| ArgbEncode(nTransparency, 210, 210, 210)}; | |
| for (FX_COLORREF ref : refs) { | |
| pDevice->DrawStrokeLine(&mtUser2Device, ptTop, ptBottom, ref, 1.0f); | |
| ptTop.x += 1.0f; | |
| ptBottom.x += 1.0f; | |
| } | |
| // draw friction | |
| if (rectWnd.Height() <= 8.0f) | |
| return; | |
| FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120); | |
| float nFrictionWidth = 5.0f; | |
| float nFrictionHeight = 5.5f; | |
| CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f, | |
| ptCenter.y - nFrictionHeight / 2.0f + 0.5f); | |
| CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f, | |
| ptCenter.y - nFrictionHeight / 2.0f + 0.5f); | |
| for (size_t i = 0; i < 3; ++i) { | |
| pDevice->DrawStrokeLine(&mtUser2Device, ptLeft, ptRight, crStroke, 1.0f); | |
| ptLeft.y += 2.0f; | |
| ptRight.y += 2.0f; | |
| } | |
| } | |
| bool CPWL_SBButton::OnLButtonDown(Mask<FWL_EVENTFLAG> nFlag, | |
| const CFX_PointF& point) { | |
| CPWL_Wnd::OnLButtonDown(nFlag, point); | |
| if (CPWL_Wnd* pParent = GetParentWindow()) | |
| pParent->NotifyLButtonDown(this, point); | |
| m_bMouseDown = true; | |
| SetCapture(); | |
| return true; | |
| } | |
| bool CPWL_SBButton::OnLButtonUp(Mask<FWL_EVENTFLAG> nFlag, | |
| const CFX_PointF& point) { | |
| CPWL_Wnd::OnLButtonUp(nFlag, point); | |
| if (CPWL_Wnd* pParent = GetParentWindow()) | |
| pParent->NotifyLButtonUp(this, point); | |
| m_bMouseDown = false; | |
| ReleaseCapture(); | |
| return true; | |
| } | |
| bool CPWL_SBButton::OnMouseMove(Mask<FWL_EVENTFLAG> nFlag, | |
| const CFX_PointF& point) { | |
| CPWL_Wnd::OnMouseMove(nFlag, point); | |
| if (CPWL_Wnd* pParent = GetParentWindow()) | |
| pParent->NotifyMouseMove(this, point); | |
| return true; | |
| } |