1 // Copyright 2021 The PDFium Authors
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 "fpdfsdk/pwl/cpwl_sbbutton.h"
8
9 #include <utility>
10 #include <vector>
11
12 #include "core/fxge/cfx_renderdevice.h"
13
CPWL_SBButton(const CreateParams & cp,std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData,Type eButtonType)14 CPWL_SBButton::CPWL_SBButton(
15 const CreateParams& cp,
16 std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData,
17 Type eButtonType)
18 : CPWL_Wnd(cp, std::move(pAttachedData)), m_eSBButtonType(eButtonType) {
19 GetCreationParams()->eCursorType = IPWL_FillerNotify::CursorStyle::kArrow;
20 }
21
22 CPWL_SBButton::~CPWL_SBButton() = default;
23
DrawThisAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)24 void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
25 const CFX_Matrix& mtUser2Device) {
26 if (!IsVisible())
27 return;
28
29 CFX_FloatRect rectWnd = GetWindowRect();
30 if (rectWnd.IsEmpty())
31 return;
32
33 CFX_PointF ptCenter = GetCenterPoint();
34 int32_t nTransparency = GetTransparency();
35
36 // draw border
37 pDevice->DrawStrokeRect(mtUser2Device, rectWnd,
38 ArgbEncode(nTransparency, 100, 100, 100), 0.0f);
39 pDevice->DrawStrokeRect(mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f),
40 ArgbEncode(nTransparency, 255, 255, 255), 1.0f);
41
42 if (m_eSBButtonType != Type::kPosButton) {
43 // draw background
44 pDevice->DrawShadow(mtUser2Device, rectWnd.GetDeflated(1.0f, 1.0f),
45 nTransparency, 80, 220);
46 // draw arrow
47 if (rectWnd.top - rectWnd.bottom > 6.0f) {
48 std::vector<CFX_PointF> pts;
49 CFX_PointF origin(rectWnd.left + 1.5f, rectWnd.bottom);
50 if (m_eSBButtonType == Type::kMinButton) {
51 static constexpr CFX_PointF kOffsetsMin[] = {
52 {2.5f, 4.0f}, {2.5f, 3.0f}, {4.5f, 5.0f}, {6.5f, 3.0f},
53 {6.5f, 4.0f}, {4.5f, 6.0f}, {2.5f, 4.0f}};
54 for (const auto& offset : kOffsetsMin) {
55 pts.push_back(origin + offset);
56 }
57 } else {
58 static constexpr CFX_PointF kOffsets[] = {
59 {2.5f, 5.0f}, {2.5f, 6.0f}, {4.5f, 4.0f}, {6.5f, 6.0f},
60 {6.5f, 5.0f}, {4.5f, 3.0f}, {2.5f, 5.0f}};
61 for (const auto& offset : kOffsets) {
62 pts.push_back(origin + offset);
63 }
64 }
65 pDevice->DrawFillArea(mtUser2Device, pts,
66 ArgbEncode(nTransparency, 255, 255, 255));
67 }
68 return;
69 }
70
71 // draw shadow effect
72 CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
73 CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
74
75 ptTop.x += 1.5f;
76 ptBottom.x += 1.5f;
77
78 const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210),
79 ArgbEncode(nTransparency, 220, 220, 220),
80 ArgbEncode(nTransparency, 240, 240, 240),
81 ArgbEncode(nTransparency, 240, 240, 240),
82 ArgbEncode(nTransparency, 210, 210, 210),
83 ArgbEncode(nTransparency, 180, 180, 180),
84 ArgbEncode(nTransparency, 150, 150, 150),
85 ArgbEncode(nTransparency, 150, 150, 150),
86 ArgbEncode(nTransparency, 180, 180, 180),
87 ArgbEncode(nTransparency, 210, 210, 210)};
88 for (FX_COLORREF ref : refs) {
89 pDevice->DrawStrokeLine(&mtUser2Device, ptTop, ptBottom, ref, 1.0f);
90
91 ptTop.x += 1.0f;
92 ptBottom.x += 1.0f;
93 }
94
95 // draw friction
96 if (rectWnd.Height() <= 8.0f)
97 return;
98
99 FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
100 float nFrictionWidth = 5.0f;
101 float nFrictionHeight = 5.5f;
102 CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
103 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
104 CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
105 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
106
107 for (size_t i = 0; i < 3; ++i) {
108 pDevice->DrawStrokeLine(&mtUser2Device, ptLeft, ptRight, crStroke, 1.0f);
109 ptLeft.y += 2.0f;
110 ptRight.y += 2.0f;
111 }
112 }
113
OnLButtonDown(Mask<FWL_EVENTFLAG> nFlag,const CFX_PointF & point)114 bool CPWL_SBButton::OnLButtonDown(Mask<FWL_EVENTFLAG> nFlag,
115 const CFX_PointF& point) {
116 CPWL_Wnd::OnLButtonDown(nFlag, point);
117
118 if (CPWL_Wnd* pParent = GetParentWindow())
119 pParent->NotifyLButtonDown(this, point);
120
121 m_bMouseDown = true;
122 SetCapture();
123
124 return true;
125 }
126
OnLButtonUp(Mask<FWL_EVENTFLAG> nFlag,const CFX_PointF & point)127 bool CPWL_SBButton::OnLButtonUp(Mask<FWL_EVENTFLAG> nFlag,
128 const CFX_PointF& point) {
129 CPWL_Wnd::OnLButtonUp(nFlag, point);
130
131 if (CPWL_Wnd* pParent = GetParentWindow())
132 pParent->NotifyLButtonUp(this, point);
133
134 m_bMouseDown = false;
135 ReleaseCapture();
136
137 return true;
138 }
139
OnMouseMove(Mask<FWL_EVENTFLAG> nFlag,const CFX_PointF & point)140 bool CPWL_SBButton::OnMouseMove(Mask<FWL_EVENTFLAG> nFlag,
141 const CFX_PointF& point) {
142 CPWL_Wnd::OnMouseMove(nFlag, point);
143
144 if (CPWL_Wnd* pParent = GetParentWindow())
145 pParent->NotifyMouseMove(this, point);
146
147 return true;
148 }
149