blob: 01ce4e6f0a990a095772ed16ee52cfe8bc0a2683 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhang60f507b2015-06-13 00:41:00 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhang633a3b72017-06-02 15:27:22 -07007#include "fpdfsdk/pdfwindow/cpwl_scroll_bar.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -04008
Dan Sinclairfb00ec22017-07-05 09:28:15 -04009#include <algorithm>
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -040010#include <sstream>
Dan Sinclairc0993812017-07-05 17:17:08 -040011#include <vector>
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -040012
dsinclair74a34fc2016-09-29 16:41:42 -070013#include "core/fxge/cfx_pathdata.h"
14#include "core/fxge/cfx_renderdevice.h"
Lei Zhang633a3b72017-06-02 15:27:22 -070015#include "fpdfsdk/pdfwindow/cpwl_utils.h"
16#include "fpdfsdk/pdfwindow/cpwl_wnd.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070017
Dan Sinclaira9e28432017-07-05 14:18:14 -040018namespace {
19
20constexpr float kButtonWidth = 9.0f;
21constexpr float kPosButtonMinWidth = 2.0f;
22constexpr float kTriangleHalfLength = 2.0f;
23
24} // namespace
25
26#define PWL_DEFAULT_HEAVYGRAYCOLOR CPWL_Color(COLORTYPE_GRAY, 0.50)
27
Nico Weber9d8ec5a2015-08-04 13:00:21 -070028PWL_FLOATRANGE::PWL_FLOATRANGE() {
29 Default();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070030}
31
Dan Sinclair05df0752017-03-14 14:43:42 -040032PWL_FLOATRANGE::PWL_FLOATRANGE(float min, float max) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070033 Set(min, max);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070034}
35
Nico Weber9d8ec5a2015-08-04 13:00:21 -070036void PWL_FLOATRANGE::Default() {
37 fMin = 0;
38 fMax = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070039}
40
Dan Sinclair05df0752017-03-14 14:43:42 -040041void PWL_FLOATRANGE::Set(float min, float max) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070042 if (min > max) {
43 fMin = max;
44 fMax = min;
45 } else {
46 fMin = min;
47 fMax = max;
48 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070049}
50
Dan Sinclair05df0752017-03-14 14:43:42 -040051bool PWL_FLOATRANGE::In(float x) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070052 return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) &&
53 (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070054}
55
Dan Sinclair05df0752017-03-14 14:43:42 -040056float PWL_FLOATRANGE::GetWidth() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 return fMax - fMin;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070058}
59
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() {
61 Default();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070062}
63
Nico Weber9d8ec5a2015-08-04 13:00:21 -070064void PWL_SCROLL_PRIVATEDATA::Default() {
65 ScrollRange.Default();
66 fScrollPos = ScrollRange.fMin;
67 fClientWidth = 0;
68 fBigStep = 10;
69 fSmallStep = 1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070070}
71
Dan Sinclair05df0752017-03-14 14:43:42 -040072void PWL_SCROLL_PRIVATEDATA::SetScrollRange(float min, float max) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073 ScrollRange.Set(min, max);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070074
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075 if (IsFloatSmaller(fScrollPos, ScrollRange.fMin))
76 fScrollPos = ScrollRange.fMin;
77 if (IsFloatBigger(fScrollPos, ScrollRange.fMax))
78 fScrollPos = ScrollRange.fMax;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070079}
80
Dan Sinclair05df0752017-03-14 14:43:42 -040081void PWL_SCROLL_PRIVATEDATA::SetClientWidth(float width) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070082 fClientWidth = width;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070083}
84
Dan Sinclair05df0752017-03-14 14:43:42 -040085void PWL_SCROLL_PRIVATEDATA::SetSmallStep(float step) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 fSmallStep = step;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070087}
88
Dan Sinclair05df0752017-03-14 14:43:42 -040089void PWL_SCROLL_PRIVATEDATA::SetBigStep(float step) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070090 fBigStep = step;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070091}
92
Dan Sinclair05df0752017-03-14 14:43:42 -040093bool PWL_SCROLL_PRIVATEDATA::SetPos(float pos) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094 if (ScrollRange.In(pos)) {
95 fScrollPos = pos;
tsepez4cf55152016-11-02 14:37:54 -070096 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097 }
tsepez4cf55152016-11-02 14:37:54 -070098 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070099}
100
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700101void PWL_SCROLL_PRIVATEDATA::AddSmall() {
102 if (!SetPos(fScrollPos + fSmallStep))
103 SetPos(ScrollRange.fMax);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700104}
105
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700106void PWL_SCROLL_PRIVATEDATA::SubSmall() {
107 if (!SetPos(fScrollPos - fSmallStep))
108 SetPos(ScrollRange.fMin);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700109}
110
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700111void PWL_SCROLL_PRIVATEDATA::AddBig() {
112 if (!SetPos(fScrollPos + fBigStep))
113 SetPos(ScrollRange.fMax);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700114}
115
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700116void PWL_SCROLL_PRIVATEDATA::SubBig() {
117 if (!SetPos(fScrollPos - fBigStep))
118 SetPos(ScrollRange.fMin);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700119}
120
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700121CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,
122 PWL_SBBUTTON_TYPE eButtonType) {
123 m_eScrollBarType = eScrollBarType;
124 m_eSBButtonType = eButtonType;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700125
tsepez4cf55152016-11-02 14:37:54 -0700126 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700127}
128
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700129CPWL_SBButton::~CPWL_SBButton() {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131CFX_ByteString CPWL_SBButton::GetClassName() const {
132 return "CPWL_SBButton";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700133}
134
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700135void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) {
136 cp.eCursorType = FXCT_ARROW;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700137}
138
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400139void CPWL_SBButton::GetThisAppearanceStream(std::ostringstream* psAppStream) {
140 CPWL_Wnd::GetThisAppearanceStream(psAppStream);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700141
142 if (!IsVisible())
143 return;
144
Tom Sepez281a9ea2016-02-26 14:24:28 -0800145 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700146 if (rectWnd.IsEmpty())
147 return;
148
Dan Sinclairf528eee2017-02-14 11:52:07 -0500149 CFX_PointF ptCenter = GetCenterPoint();
Dan Sinclairc0993812017-07-05 17:17:08 -0400150 CFX_PointF pt1;
151 CFX_PointF pt2;
152 CFX_PointF pt3;
153 if (m_eScrollBarType == SBT_HSCROLL) {
154 if (m_eSBButtonType == PSBT_MIN) {
155 pt1 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, ptCenter.y);
156 pt2 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f,
157 ptCenter.y + kTriangleHalfLength);
158 pt3 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f,
159 ptCenter.y - kTriangleHalfLength);
160 } else if (m_eSBButtonType == PSBT_MAX) {
161 pt1 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, ptCenter.y);
162 pt2 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f,
163 ptCenter.y + kTriangleHalfLength);
164 pt3 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f,
165 ptCenter.y - kTriangleHalfLength);
166 }
167 } else {
168 if (m_eSBButtonType == PSBT_MIN) {
169 pt1 = CFX_PointF(ptCenter.x - kTriangleHalfLength,
170 ptCenter.y - kTriangleHalfLength * 0.5f);
171 pt2 = CFX_PointF(ptCenter.x + kTriangleHalfLength,
172 ptCenter.y - kTriangleHalfLength * 0.5f);
173 pt3 = CFX_PointF(ptCenter.x, ptCenter.y + kTriangleHalfLength * 0.5f);
174 } else if (m_eSBButtonType == PSBT_MAX) {
175 pt1 = CFX_PointF(ptCenter.x - kTriangleHalfLength,
176 ptCenter.y + kTriangleHalfLength * 0.5f);
177 pt2 = CFX_PointF(ptCenter.x + kTriangleHalfLength,
178 ptCenter.y + kTriangleHalfLength * 0.5f);
179 pt3 = CFX_PointF(ptCenter.x, ptCenter.y - kTriangleHalfLength * 0.5f);
180 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700181 }
182
Dan Sinclairc0993812017-07-05 17:17:08 -0400183 *psAppStream << "q\n";
184 if (m_eSBButtonType != PSBT_POS) {
185 if (rectWnd.right - rectWnd.left > kTriangleHalfLength * 2 &&
186 rectWnd.top - rectWnd.bottom > kTriangleHalfLength) {
187 *psAppStream << "0 g\n"
188 << pt1.x << " " << pt1.y << " m\n"
189 << pt2.x << " " << pt2.y << " l\n"
190 << pt3.x << " " << pt3.y << " l\n"
191 << pt1.x << " " << pt1.y << " l f\n";
192 }
193 }
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400194 *psAppStream << "Q\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700195}
196
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700197void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800198 CFX_Matrix* pUser2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 if (!IsVisible())
200 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700201
Tom Sepez281a9ea2016-02-26 14:24:28 -0800202 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 if (rectWnd.IsEmpty())
204 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700205
Dan Sinclairf528eee2017-02-14 11:52:07 -0500206 CFX_PointF ptCenter = GetCenterPoint();
Dan Sinclairfc54e052017-02-23 09:59:05 -0500207 int32_t nTransparency = GetTransparency();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700208
Dan Sinclairc0993812017-07-05 17:17:08 -0400209 if (m_eScrollBarType == SBT_HSCROLL) {
210 CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700211
Dan Sinclairc0993812017-07-05 17:17:08 -0400212 CFX_PointF pt1;
213 CFX_PointF pt2;
214 CFX_PointF pt3;
215 if (m_eSBButtonType == PSBT_MIN) {
216 pt1 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, ptCenter.y);
217 pt2 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f,
218 ptCenter.y + kTriangleHalfLength);
219 pt3 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f,
220 ptCenter.y - kTriangleHalfLength);
221 } else if (m_eSBButtonType == PSBT_MAX) {
222 pt1 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, ptCenter.y);
223 pt2 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f,
224 ptCenter.y + kTriangleHalfLength);
225 pt3 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f,
226 ptCenter.y - kTriangleHalfLength);
227 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700228
Dan Sinclairc0993812017-07-05 17:17:08 -0400229 if (rectWnd.right - rectWnd.left > kTriangleHalfLength * 2 &&
230 rectWnd.top - rectWnd.bottom > kTriangleHalfLength) {
231 CFX_PathData path;
232 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
233 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
234 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
235 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236
Dan Sinclairc0993812017-07-05 17:17:08 -0400237 pDevice->DrawPath(&path, pUser2Device, nullptr,
238 PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency), 0,
239 FXFILL_ALTERNATE);
240 }
241 return;
242 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700243
Dan Sinclairc0993812017-07-05 17:17:08 -0400244 // draw border
245 CFX_FloatRect rcDraw = rectWnd;
246 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
247 ArgbEncode(nTransparency, 100, 100, 100), 0.0f);
248
249 // draw inner border
250 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
251 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
252 ArgbEncode(nTransparency, 255, 255, 255), 1.0f);
253
254 if (m_eSBButtonType != PSBT_POS) {
255 // draw background
256 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f);
257
258 if (IsEnabled()) {
259 CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw,
260 nTransparency, 80, 220);
261 } else {
262 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
263 ArgbEncode(255, 255, 255, 255));
264 }
265
266 // draw arrow
267 if (rectWnd.top - rectWnd.bottom > 6.0f) {
268 float fX = rectWnd.left + 1.5f;
269 float fY = rectWnd.bottom;
270 std::vector<CFX_PointF> pts;
271 if (m_eSBButtonType == PSBT_MIN) {
272 pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f));
273 pts.push_back(CFX_PointF(fX + 2.5f, fY + 3.0f));
274 pts.push_back(CFX_PointF(fX + 4.5f, fY + 5.0f));
275 pts.push_back(CFX_PointF(fX + 6.5f, fY + 3.0f));
276 pts.push_back(CFX_PointF(fX + 6.5f, fY + 4.0f));
277 pts.push_back(CFX_PointF(fX + 4.5f, fY + 6.0f));
278 pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f));
279 } else {
280 pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f));
281 pts.push_back(CFX_PointF(fX + 2.5f, fY + 6.0f));
282 pts.push_back(CFX_PointF(fX + 4.5f, fY + 4.0f));
283 pts.push_back(CFX_PointF(fX + 6.5f, fY + 6.0f));
284 pts.push_back(CFX_PointF(fX + 6.5f, fY + 5.0f));
285 pts.push_back(CFX_PointF(fX + 4.5f, fY + 3.0f));
286 pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700287 }
Dan Sinclairc0993812017-07-05 17:17:08 -0400288 CPWL_Utils::DrawFillArea(pDevice, pUser2Device, pts.data(), 7,
289 IsEnabled()
290 ? ArgbEncode(nTransparency, 255, 255, 255)
291 : PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
292 }
293 return;
294 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700295
Dan Sinclairc0993812017-07-05 17:17:08 -0400296 if (IsEnabled()) {
297 // draw shadow effect
298 CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
299 CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700300
Dan Sinclairc0993812017-07-05 17:17:08 -0400301 ptTop.x += 1.5f;
302 ptBottom.x += 1.5f;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700303
Dan Sinclairc0993812017-07-05 17:17:08 -0400304 const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210),
305 ArgbEncode(nTransparency, 220, 220, 220),
306 ArgbEncode(nTransparency, 240, 240, 240),
307 ArgbEncode(nTransparency, 240, 240, 240),
308 ArgbEncode(nTransparency, 210, 210, 210),
309 ArgbEncode(nTransparency, 180, 180, 180),
310 ArgbEncode(nTransparency, 150, 150, 150),
311 ArgbEncode(nTransparency, 150, 150, 150),
312 ArgbEncode(nTransparency, 180, 180, 180),
313 ArgbEncode(nTransparency, 210, 210, 210)};
314 for (auto* it = std::begin(refs); it < std::end(refs); ++it) {
315 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, *it,
316 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700317
Dan Sinclairc0993812017-07-05 17:17:08 -0400318 ptTop.x += 1.0f;
319 ptBottom.x += 1.0f;
320 }
321 } else {
322 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
323 ArgbEncode(255, 255, 255, 255));
324 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700325
Dan Sinclairc0993812017-07-05 17:17:08 -0400326 // draw friction
327 if (rectWnd.Height() <= 8.0f)
328 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700329
Dan Sinclairc0993812017-07-05 17:17:08 -0400330 FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
331 if (!IsEnabled())
332 crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700333
Dan Sinclairc0993812017-07-05 17:17:08 -0400334 float nFrictionWidth = 5.0f;
335 float nFrictionHeight = 5.5f;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700336
Dan Sinclairc0993812017-07-05 17:17:08 -0400337 CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
338 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
339 CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
340 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341
Dan Sinclairc0993812017-07-05 17:17:08 -0400342 for (size_t i = 0; i < 3; ++i) {
343 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, crStroke,
344 1.0f);
345 ptLeft.y += 2.0f;
346 ptRight.y += 2.0f;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700347 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700348}
349
Dan Sinclairf528eee2017-02-14 11:52:07 -0500350bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700351 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700352
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700353 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400354 pParent->NotifyLButtonDown(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355
tsepez4cf55152016-11-02 14:37:54 -0700356 m_bMouseDown = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357 SetCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700358
tsepez4cf55152016-11-02 14:37:54 -0700359 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700360}
361
Dan Sinclairf528eee2017-02-14 11:52:07 -0500362bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700364
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700365 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400366 pParent->NotifyLButtonUp(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700367
tsepez4cf55152016-11-02 14:37:54 -0700368 m_bMouseDown = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700369 ReleaseCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700370
tsepez4cf55152016-11-02 14:37:54 -0700371 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700372}
373
Dan Sinclairf528eee2017-02-14 11:52:07 -0500374bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700375 CPWL_Wnd::OnMouseMove(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700376
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400377 if (CPWL_Wnd* pParent = GetParentWindow())
378 pParent->NotifyMouseMove(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700379
tsepez4cf55152016-11-02 14:37:54 -0700380 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700381}
382
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)
384 : m_sbType(sbType),
thestig1cd352e2016-06-07 17:53:06 -0700385 m_pMinButton(nullptr),
386 m_pMaxButton(nullptr),
387 m_pPosButton(nullptr),
tsepez4cf55152016-11-02 14:37:54 -0700388 m_bMouseDown(false),
389 m_bMinOrMax(false),
390 m_bNotifyForever(true) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700391
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700392CPWL_ScrollBar::~CPWL_ScrollBar() {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700393
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394CFX_ByteString CPWL_ScrollBar::GetClassName() const {
395 return "CPWL_ScrollBar";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700396}
397
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) {
399 cp.eCursorType = FXCT_ARROW;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700400}
401
Tom Sepez5e042a12017-05-30 14:13:44 -0700402void CPWL_ScrollBar::OnDestroy() {
403 // Until cleanup takes place in the virtual destructor for CPWL_Wnd
404 // subclasses, implement the virtual OnDestroy method that does the
405 // cleanup first, then invokes the superclass OnDestroy ... gee,
406 // like a dtor would.
407 m_pMinButton.Release();
408 m_pMaxButton.Release();
409 m_pPosButton.Release();
410 CPWL_Wnd::OnDestroy();
411}
412
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700413void CPWL_ScrollBar::RePosChildWnd() {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800414 CFX_FloatRect rcClient = GetClientRect();
415 CFX_FloatRect rcMinButton, rcMaxButton;
Dan Sinclair05df0752017-03-14 14:43:42 -0400416 float fBWidth = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417
418 switch (m_sbType) {
419 case SBT_HSCROLL:
420 if (rcClient.right - rcClient.left >
Dan Sinclaira9e28432017-07-05 14:18:14 -0400421 kButtonWidth * 2 + kPosButtonMinWidth + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800422 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400423 rcClient.left + kButtonWidth, rcClient.top);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800424 rcMaxButton =
Dan Sinclaira9e28432017-07-05 14:18:14 -0400425 CFX_FloatRect(rcClient.right - kButtonWidth, rcClient.bottom,
426 rcClient.right, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427 } else {
Dan Sinclaira9e28432017-07-05 14:18:14 -0400428 fBWidth = (rcClient.right - rcClient.left - kPosButtonMinWidth - 2) / 2;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429
430 if (fBWidth > 0) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800431 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
432 rcClient.left + fBWidth, rcClient.top);
433 rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom,
434 rcClient.right, rcClient.top);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800435 } else {
tsepez4cf55152016-11-02 14:37:54 -0700436 SetVisible(false);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800437 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700438 }
439 break;
440 case SBT_VSCROLL:
441 if (IsFloatBigger(rcClient.top - rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400442 kButtonWidth * 2 + kPosButtonMinWidth + 2)) {
443 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - kButtonWidth,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800444 rcClient.right, rcClient.top);
445 rcMaxButton =
446 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400447 rcClient.bottom + kButtonWidth);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 } else {
Dan Sinclaira9e28432017-07-05 14:18:14 -0400449 fBWidth = (rcClient.top - rcClient.bottom - kPosButtonMinWidth - 2) / 2;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700450
451 if (IsFloatBigger(fBWidth, 0)) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800452 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth,
453 rcClient.right, rcClient.top);
454 rcMaxButton =
455 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
456 rcClient.bottom + fBWidth);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800457 } else {
tsepez4cf55152016-11-02 14:37:54 -0700458 SetVisible(false);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800459 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700460 }
461 break;
462 }
463
464 if (m_pMinButton)
tsepez4cf55152016-11-02 14:37:54 -0700465 m_pMinButton->Move(rcMinButton, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700466 if (m_pMaxButton)
tsepez4cf55152016-11-02 14:37:54 -0700467 m_pMaxButton->Move(rcMaxButton, true, false);
468 MovePosButton(false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700469}
470
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400471void CPWL_ScrollBar::GetThisAppearanceStream(std::ostringstream* psAppStream) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800472 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400474 if (!IsVisible() || rectWnd.IsEmpty())
475 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700476
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400477 *psAppStream << "q\n"
478 << "0 w\n"
479 << CPWL_Utils::GetColorAppStream(GetBackgroundColor(), true)
480 << rectWnd.left << " " << rectWnd.bottom << " "
481 << rectWnd.right - rectWnd.left << " "
482 << rectWnd.top - rectWnd.bottom << " re b Q\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700483}
484
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800486 CFX_Matrix* pUser2Device) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800487 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488
489 if (IsVisible() && !rectWnd.IsEmpty()) {
490 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rectWnd,
491 GetBackgroundColor(), GetTransparency());
492
493 CPWL_Utils::DrawStrokeLine(
494 pDevice, pUser2Device,
Dan Sinclairf528eee2017-02-14 11:52:07 -0500495 CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f),
496 CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
498
499 CPWL_Utils::DrawStrokeLine(
500 pDevice, pUser2Device,
Dan Sinclairf528eee2017-02-14 11:52:07 -0500501 CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f),
502 CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700503 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
504 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700505}
506
Dan Sinclairf528eee2017-02-14 11:52:07 -0500507bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700508 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700509
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700510 if (HasFlag(PWS_AUTOTRANSPARENT)) {
511 if (GetTransparency() != 255) {
512 SetTransparency(255);
513 InvalidateRect();
514 }
515 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700516
Tom Sepez281a9ea2016-02-26 14:24:28 -0800517 CFX_FloatRect rcMinArea, rcMaxArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700518
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700519 if (m_pPosButton && m_pPosButton->IsVisible()) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800520 CFX_FloatRect rcClient = GetClientRect();
521 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
Lei Zhang60f507b2015-06-13 00:41:00 -0700522
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700523 switch (m_sbType) {
524 case SBT_HSCROLL:
Dan Sinclaira9e28432017-07-05 14:18:14 -0400525 rcMinArea = CFX_FloatRect(rcClient.left + kButtonWidth, rcClient.bottom,
526 rcPosButton.left, rcClient.top);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800527 rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400528 rcClient.right - kButtonWidth, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700529
530 break;
531 case SBT_VSCROLL:
Dan Sinclaira9e28432017-07-05 14:18:14 -0400532 rcMinArea = CFX_FloatRect(rcClient.left, rcPosButton.top,
533 rcClient.right, rcClient.top - kButtonWidth);
534 rcMaxArea = CFX_FloatRect(rcClient.left, rcClient.bottom + kButtonWidth,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800535 rcClient.right, rcPosButton.bottom);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536 break;
537 }
538
539 rcMinArea.Normalize();
540 rcMaxArea.Normalize();
541
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500542 if (rcMinArea.Contains(point)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700543 m_sData.SubBig();
tsepez4cf55152016-11-02 14:37:54 -0700544 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700545 NotifyScrollWindow();
546 }
547
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500548 if (rcMaxArea.Contains(point)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700549 m_sData.AddBig();
tsepez4cf55152016-11-02 14:37:54 -0700550 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700551 NotifyScrollWindow();
552 }
553 }
554
tsepez4cf55152016-11-02 14:37:54 -0700555 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700556}
557
Dan Sinclairf528eee2017-02-14 11:52:07 -0500558bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700560
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700561 if (HasFlag(PWS_AUTOTRANSPARENT)) {
Dan Sinclairfc54e052017-02-23 09:59:05 -0500562 if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) {
563 SetTransparency(PWL_SCROLLBAR_TRANSPARENCY);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700564 InvalidateRect();
565 }
566 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700567
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 EndTimer();
tsepez4cf55152016-11-02 14:37:54 -0700569 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700570
tsepez4cf55152016-11-02 14:37:54 -0700571 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700572}
573
Dan Sinclairfb00ec22017-07-05 09:28:15 -0400574void CPWL_ScrollBar::SetScrollInfo(const PWL_SCROLL_INFO& info) {
575 if (info == m_OriginInfo)
576 return;
577
578 m_OriginInfo = info;
579 float fMax =
580 std::max(0.0f, info.fContentMax - info.fContentMin - info.fPlateWidth);
581 SetScrollRange(0, fMax, info.fPlateWidth);
582 SetScrollStep(info.fBigStep, info.fSmallStep);
583}
584
Dan Sinclair7e0336e2017-07-05 09:39:50 -0400585void CPWL_ScrollBar::SetScrollPosition(float pos) {
586 switch (m_sbType) {
587 case SBT_HSCROLL:
588 pos = pos - m_OriginInfo.fContentMin;
589 break;
590 case SBT_VSCROLL:
591 pos = m_OriginInfo.fContentMax - pos;
592 break;
593 }
594 SetScrollPos(pos);
595}
596
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400597void CPWL_ScrollBar::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
598 if (child == m_pMinButton)
599 OnMinButtonLBDown(pos);
600 else if (child == m_pMaxButton)
601 OnMaxButtonLBDown(pos);
602 else if (child == m_pPosButton)
603 OnPosButtonLBDown(pos);
604}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700605
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400606void CPWL_ScrollBar::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
607 if (child == m_pMinButton)
608 OnMinButtonLBUp(pos);
609 else if (child == m_pMaxButton)
610 OnMaxButtonLBUp(pos);
611 else if (child == m_pPosButton)
612 OnPosButtonLBUp(pos);
613}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700614
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400615void CPWL_ScrollBar::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {
616 if (child == m_pMinButton)
617 OnMinButtonMouseMove(pos);
618 else if (child == m_pMaxButton)
619 OnMaxButtonMouseMove(pos);
620 else if (child == m_pPosButton)
621 OnPosButtonMouseMove(pos);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700622}
623
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700624void CPWL_ScrollBar::CreateButtons(const PWL_CREATEPARAM& cp) {
625 PWL_CREATEPARAM scp = cp;
626 scp.pParentWnd = this;
627 scp.dwBorderWidth = 2;
dsinclair92cb5e52016-05-16 11:38:28 -0700628 scp.nBorderStyle = BorderStyle::BEVELED;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700629
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700630 scp.dwFlags =
631 PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700632
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700633 if (!m_pMinButton) {
634 m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN);
635 m_pMinButton->Create(scp);
636 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700637
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700638 if (!m_pMaxButton) {
639 m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX);
640 m_pMaxButton->Create(scp);
641 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700642
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700643 if (!m_pPosButton) {
644 m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS);
tsepez4cf55152016-11-02 14:37:54 -0700645 m_pPosButton->SetVisible(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700646 m_pPosButton->Create(scp);
647 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700648}
649
Dan Sinclair05df0752017-03-14 14:43:42 -0400650float CPWL_ScrollBar::GetScrollBarWidth() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700651 if (!IsVisible())
652 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700653
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700654 return PWL_SCROLLBAR_WIDTH;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700655}
656
Dan Sinclair05df0752017-03-14 14:43:42 -0400657void CPWL_ScrollBar::SetScrollRange(float fMin,
658 float fMax,
659 float fClientWidth) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700660 if (m_pPosButton) {
661 m_sData.SetScrollRange(fMin, fMax);
662 m_sData.SetClientWidth(fClientWidth);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700663
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700664 if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
tsepez4cf55152016-11-02 14:37:54 -0700665 m_pPosButton->SetVisible(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700666 } else {
tsepez4cf55152016-11-02 14:37:54 -0700667 m_pPosButton->SetVisible(true);
668 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700669 }
670 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700671}
672
Dan Sinclair05df0752017-03-14 14:43:42 -0400673void CPWL_ScrollBar::SetScrollPos(float fPos) {
674 float fOldPos = m_sData.fScrollPos;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700675 m_sData.SetPos(fPos);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700676 if (!IsFloatEqual(m_sData.fScrollPos, fOldPos))
tsepez4cf55152016-11-02 14:37:54 -0700677 MovePosButton(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700678}
679
Dan Sinclair05df0752017-03-14 14:43:42 -0400680void CPWL_ScrollBar::SetScrollStep(float fBigStep, float fSmallStep) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700681 m_sData.SetBigStep(fBigStep);
682 m_sData.SetSmallStep(fSmallStep);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700683}
684
tsepez4cf55152016-11-02 14:37:54 -0700685void CPWL_ScrollBar::MovePosButton(bool bRefresh) {
Lei Zhang96660d62015-12-14 18:27:25 -0800686 ASSERT(m_pMinButton);
687 ASSERT(m_pMaxButton);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700688
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700689 if (m_pPosButton->IsVisible()) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800690 CFX_FloatRect rcClient;
691 CFX_FloatRect rcPosArea, rcPosButton;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700692
693 rcClient = GetClientRect();
694 rcPosArea = GetScrollArea();
695
Dan Sinclair05df0752017-03-14 14:43:42 -0400696 float fLeft, fRight, fTop, fBottom;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700697
698 switch (m_sbType) {
699 case SBT_HSCROLL:
700 fLeft = TrueToFace(m_sData.fScrollPos);
701 fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
702
Dan Sinclaira9e28432017-07-05 14:18:14 -0400703 if (fRight - fLeft < kPosButtonMinWidth)
704 fRight = fLeft + kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700705
706 if (fRight > rcPosArea.right) {
707 fRight = rcPosArea.right;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400708 fLeft = fRight - kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700709 }
710
Tom Sepez281a9ea2016-02-26 14:24:28 -0800711 rcPosButton =
712 CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700713
714 break;
715 case SBT_VSCROLL:
716 fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
717 fTop = TrueToFace(m_sData.fScrollPos);
718
Dan Sinclaira9e28432017-07-05 14:18:14 -0400719 if (IsFloatSmaller(fTop - fBottom, kPosButtonMinWidth))
720 fBottom = fTop - kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700721
722 if (IsFloatSmaller(fBottom, rcPosArea.bottom)) {
723 fBottom = rcPosArea.bottom;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400724 fTop = fBottom + kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700725 }
726
Tom Sepez281a9ea2016-02-26 14:24:28 -0800727 rcPosButton =
728 CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700729
730 break;
731 }
732
tsepez4cf55152016-11-02 14:37:54 -0700733 m_pPosButton->Move(rcPosButton, true, bRefresh);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700734 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700735}
736
Dan Sinclairf528eee2017-02-14 11:52:07 -0500737void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700738 m_sData.SubSmall();
tsepez4cf55152016-11-02 14:37:54 -0700739 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700740 NotifyScrollWindow();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700741
tsepez4cf55152016-11-02 14:37:54 -0700742 m_bMinOrMax = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700743
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700744 EndTimer();
745 BeginTimer(100);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700746}
747
Dan Sinclairf528eee2017-02-14 11:52:07 -0500748void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700749
Dan Sinclairf528eee2017-02-14 11:52:07 -0500750void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700751
Dan Sinclairf528eee2017-02-14 11:52:07 -0500752void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700753 m_sData.AddSmall();
tsepez4cf55152016-11-02 14:37:54 -0700754 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700755 NotifyScrollWindow();
756
tsepez4cf55152016-11-02 14:37:54 -0700757 m_bMinOrMax = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700758
759 EndTimer();
760 BeginTimer(100);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700761}
762
Dan Sinclairf528eee2017-02-14 11:52:07 -0500763void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700764
Dan Sinclairf528eee2017-02-14 11:52:07 -0500765void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700766
Dan Sinclairf528eee2017-02-14 11:52:07 -0500767void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) {
tsepez4cf55152016-11-02 14:37:54 -0700768 m_bMouseDown = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700769
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700770 if (m_pPosButton) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800771 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700772
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700773 switch (m_sbType) {
774 case SBT_HSCROLL:
775 m_nOldPos = point.x;
776 m_fOldPosButton = rcPosButton.left;
777 break;
778 case SBT_VSCROLL:
779 m_nOldPos = point.y;
780 m_fOldPosButton = rcPosButton.top;
781 break;
782 }
783 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700784}
785
Dan Sinclairf528eee2017-02-14 11:52:07 -0500786void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700787 if (m_bMouseDown) {
788 if (!m_bNotifyForever)
789 NotifyScrollWindow();
790 }
tsepez4cf55152016-11-02 14:37:54 -0700791 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700792}
793
Dan Sinclairf528eee2017-02-14 11:52:07 -0500794void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400795 float fOldScrollPos = m_sData.fScrollPos;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700796
Dan Sinclair05df0752017-03-14 14:43:42 -0400797 float fNewPos = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700798
799 switch (m_sbType) {
800 case SBT_HSCROLL:
Dan Sinclair669a4182017-04-03 14:51:45 -0400801 if (fabs(point.x - m_nOldPos) < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700802 return;
803 fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos);
804 break;
805 case SBT_VSCROLL:
Dan Sinclair669a4182017-04-03 14:51:45 -0400806 if (fabs(point.y - m_nOldPos) < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700807 return;
808 fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos);
809 break;
810 }
811
812 if (m_bMouseDown) {
813 switch (m_sbType) {
814 case SBT_HSCROLL:
815
816 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
817 fNewPos = m_sData.ScrollRange.fMin;
818 }
819
820 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
821 fNewPos = m_sData.ScrollRange.fMax;
822 }
823
824 m_sData.SetPos(fNewPos);
825
826 break;
827 case SBT_VSCROLL:
828
829 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
830 fNewPos = m_sData.ScrollRange.fMin;
831 }
832
833 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
834 fNewPos = m_sData.ScrollRange.fMax;
835 }
836
837 m_sData.SetPos(fNewPos);
838
839 break;
840 }
841
842 if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) {
tsepez4cf55152016-11-02 14:37:54 -0700843 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700844
845 if (m_bNotifyForever)
846 NotifyScrollWindow();
847 }
848 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700849}
850
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700851void CPWL_ScrollBar::NotifyScrollWindow() {
Dan Sinclair63fbd8d2017-07-05 14:10:36 -0400852 CPWL_Wnd* pParent = GetParentWindow();
853 if (!pParent || m_sbType != SBT_VSCROLL)
854 return;
855
856 pParent->ScrollWindowVertically(m_OriginInfo.fContentMax -
857 m_sData.fScrollPos);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700858}
859
Tom Sepez281a9ea2016-02-26 14:24:28 -0800860CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const {
861 CFX_FloatRect rcClient = GetClientRect();
862 CFX_FloatRect rcArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700863
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700864 if (!m_pMinButton || !m_pMaxButton)
865 return rcClient;
Lei Zhang60f507b2015-06-13 00:41:00 -0700866
Tom Sepez281a9ea2016-02-26 14:24:28 -0800867 CFX_FloatRect rcMin = m_pMinButton->GetWindowRect();
868 CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700869
Dan Sinclair05df0752017-03-14 14:43:42 -0400870 float fMinWidth = rcMin.right - rcMin.left;
871 float fMinHeight = rcMin.top - rcMin.bottom;
872 float fMaxWidth = rcMax.right - rcMax.left;
873 float fMaxHeight = rcMax.top - rcMax.bottom;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700874
875 switch (m_sbType) {
876 case SBT_HSCROLL:
877 if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800878 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
879 rcClient.right - fMaxWidth - 1, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700880 } else {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800881 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
882 rcClient.left + fMinWidth + 1, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700883 }
884 break;
885 case SBT_VSCROLL:
886 if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800887 rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
888 rcClient.right, rcClient.top - fMaxHeight - 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700889 } else {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800890 rcArea =
891 CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
892 rcClient.right, rcClient.bottom + fMinHeight + 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700893 }
894 break;
895 }
896
897 rcArea.Normalize();
898
899 return rcArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700900}
901
Dan Sinclair05df0752017-03-14 14:43:42 -0400902float CPWL_ScrollBar::TrueToFace(float fTrue) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800903 CFX_FloatRect rcPosArea;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700904 rcPosArea = GetScrollArea();
905
Dan Sinclair05df0752017-03-14 14:43:42 -0400906 float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700907 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
908
Dan Sinclair05df0752017-03-14 14:43:42 -0400909 float fFace = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700910
911 switch (m_sbType) {
912 case SBT_HSCROLL:
913 fFace = rcPosArea.left +
914 fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth;
915 break;
916 case SBT_VSCROLL:
917 fFace = rcPosArea.top -
918 fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth;
919 break;
920 }
921
922 return fFace;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700923}
924
Dan Sinclair05df0752017-03-14 14:43:42 -0400925float CPWL_ScrollBar::FaceToTrue(float fFace) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800926 CFX_FloatRect rcPosArea;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700927 rcPosArea = GetScrollArea();
928
Dan Sinclair05df0752017-03-14 14:43:42 -0400929 float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700930 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
931
Dan Sinclair05df0752017-03-14 14:43:42 -0400932 float fTrue = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700933
934 switch (m_sbType) {
935 case SBT_HSCROLL:
936 fTrue = (fFace - rcPosArea.left) * fFactWidth /
937 (rcPosArea.right - rcPosArea.left);
938 break;
939 case SBT_VSCROLL:
940 fTrue = (rcPosArea.top - fFace) * fFactWidth /
941 (rcPosArea.top - rcPosArea.bottom);
942 break;
943 }
944
945 return fTrue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700946}
947
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700948void CPWL_ScrollBar::CreateChildWnd(const PWL_CREATEPARAM& cp) {
949 CreateButtons(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700950}
951
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700952void CPWL_ScrollBar::TimerProc() {
953 PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700954 if (m_bMinOrMax)
955 m_sData.SubSmall();
956 else
957 m_sData.AddSmall();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700958
tsepezf86ca382016-09-13 12:23:30 -0700959 if (sTemp != m_sData) {
tsepez4cf55152016-11-02 14:37:54 -0700960 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700961 NotifyScrollWindow();
962 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700963}