blob: 491d0b38762d96854397b22d1a58a322bd232ab9 [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
Dan Sinclair7f55a542017-07-13 14:17:10 -040026#define PWL_DEFAULT_HEAVYGRAYCOLOR CFX_Color(COLORTYPE_GRAY, 0.50)
Dan Sinclaira9e28432017-07-05 14:18:14 -040027
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
dan sinclairadf922f2017-07-12 21:56:27 -0400250 rcDraw = rectWnd;
251 if (!rcDraw.IsEmpty()) {
252 rcDraw.Deflate(0.5f, 0.5f);
253 rcDraw.Normalize();
254 }
Dan Sinclairc0993812017-07-05 17:17:08 -0400255 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
256 ArgbEncode(nTransparency, 255, 255, 255), 1.0f);
257
258 if (m_eSBButtonType != PSBT_POS) {
259 // draw background
dan sinclairadf922f2017-07-12 21:56:27 -0400260 rcDraw = rectWnd;
261 if (!rcDraw.IsEmpty()) {
262 rcDraw.Deflate(1.0f, 1.0f);
263 rcDraw.Normalize();
264 }
Dan Sinclairc0993812017-07-05 17:17:08 -0400265 if (IsEnabled()) {
266 CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw,
267 nTransparency, 80, 220);
268 } else {
269 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
270 ArgbEncode(255, 255, 255, 255));
271 }
272
273 // draw arrow
274 if (rectWnd.top - rectWnd.bottom > 6.0f) {
275 float fX = rectWnd.left + 1.5f;
276 float fY = rectWnd.bottom;
277 std::vector<CFX_PointF> pts;
278 if (m_eSBButtonType == PSBT_MIN) {
279 pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f));
280 pts.push_back(CFX_PointF(fX + 2.5f, fY + 3.0f));
281 pts.push_back(CFX_PointF(fX + 4.5f, fY + 5.0f));
282 pts.push_back(CFX_PointF(fX + 6.5f, fY + 3.0f));
283 pts.push_back(CFX_PointF(fX + 6.5f, fY + 4.0f));
284 pts.push_back(CFX_PointF(fX + 4.5f, fY + 6.0f));
285 pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f));
286 } else {
287 pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f));
288 pts.push_back(CFX_PointF(fX + 2.5f, fY + 6.0f));
289 pts.push_back(CFX_PointF(fX + 4.5f, fY + 4.0f));
290 pts.push_back(CFX_PointF(fX + 6.5f, fY + 6.0f));
291 pts.push_back(CFX_PointF(fX + 6.5f, fY + 5.0f));
292 pts.push_back(CFX_PointF(fX + 4.5f, fY + 3.0f));
293 pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 }
Dan Sinclairc0993812017-07-05 17:17:08 -0400295 CPWL_Utils::DrawFillArea(pDevice, pUser2Device, pts.data(), 7,
296 IsEnabled()
297 ? ArgbEncode(nTransparency, 255, 255, 255)
298 : PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
299 }
300 return;
301 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700302
Dan Sinclairc0993812017-07-05 17:17:08 -0400303 if (IsEnabled()) {
304 // draw shadow effect
305 CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
306 CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700307
Dan Sinclairc0993812017-07-05 17:17:08 -0400308 ptTop.x += 1.5f;
309 ptBottom.x += 1.5f;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700310
Dan Sinclairc0993812017-07-05 17:17:08 -0400311 const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210),
312 ArgbEncode(nTransparency, 220, 220, 220),
313 ArgbEncode(nTransparency, 240, 240, 240),
314 ArgbEncode(nTransparency, 240, 240, 240),
315 ArgbEncode(nTransparency, 210, 210, 210),
316 ArgbEncode(nTransparency, 180, 180, 180),
317 ArgbEncode(nTransparency, 150, 150, 150),
318 ArgbEncode(nTransparency, 150, 150, 150),
319 ArgbEncode(nTransparency, 180, 180, 180),
320 ArgbEncode(nTransparency, 210, 210, 210)};
321 for (auto* it = std::begin(refs); it < std::end(refs); ++it) {
322 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom, *it,
323 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700324
Dan Sinclairc0993812017-07-05 17:17:08 -0400325 ptTop.x += 1.0f;
326 ptBottom.x += 1.0f;
327 }
328 } else {
329 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
330 ArgbEncode(255, 255, 255, 255));
331 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700332
Dan Sinclairc0993812017-07-05 17:17:08 -0400333 // draw friction
334 if (rectWnd.Height() <= 8.0f)
335 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700336
Dan Sinclairc0993812017-07-05 17:17:08 -0400337 FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
338 if (!IsEnabled())
339 crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700340
Dan Sinclairc0993812017-07-05 17:17:08 -0400341 float nFrictionWidth = 5.0f;
342 float nFrictionHeight = 5.5f;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700343
Dan Sinclairc0993812017-07-05 17:17:08 -0400344 CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
345 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
346 CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
347 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700348
Dan Sinclairc0993812017-07-05 17:17:08 -0400349 for (size_t i = 0; i < 3; ++i) {
350 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight, crStroke,
351 1.0f);
352 ptLeft.y += 2.0f;
353 ptRight.y += 2.0f;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700354 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355}
356
Dan Sinclairf528eee2017-02-14 11:52:07 -0500357bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700358 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700359
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400361 pParent->NotifyLButtonDown(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700362
tsepez4cf55152016-11-02 14:37:54 -0700363 m_bMouseDown = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364 SetCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700365
tsepez4cf55152016-11-02 14:37:54 -0700366 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700367}
368
Dan Sinclairf528eee2017-02-14 11:52:07 -0500369bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700371
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700372 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400373 pParent->NotifyLButtonUp(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700374
tsepez4cf55152016-11-02 14:37:54 -0700375 m_bMouseDown = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 ReleaseCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700377
tsepez4cf55152016-11-02 14:37:54 -0700378 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700379}
380
Dan Sinclairf528eee2017-02-14 11:52:07 -0500381bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700382 CPWL_Wnd::OnMouseMove(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700383
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400384 if (CPWL_Wnd* pParent = GetParentWindow())
385 pParent->NotifyMouseMove(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700386
tsepez4cf55152016-11-02 14:37:54 -0700387 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700388}
389
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700390CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)
391 : m_sbType(sbType),
thestig1cd352e2016-06-07 17:53:06 -0700392 m_pMinButton(nullptr),
393 m_pMaxButton(nullptr),
394 m_pPosButton(nullptr),
tsepez4cf55152016-11-02 14:37:54 -0700395 m_bMouseDown(false),
396 m_bMinOrMax(false),
397 m_bNotifyForever(true) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700398
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700399CPWL_ScrollBar::~CPWL_ScrollBar() {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700400
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700401CFX_ByteString CPWL_ScrollBar::GetClassName() const {
402 return "CPWL_ScrollBar";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700403}
404
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) {
406 cp.eCursorType = FXCT_ARROW;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700407}
408
Tom Sepez5e042a12017-05-30 14:13:44 -0700409void CPWL_ScrollBar::OnDestroy() {
410 // Until cleanup takes place in the virtual destructor for CPWL_Wnd
411 // subclasses, implement the virtual OnDestroy method that does the
412 // cleanup first, then invokes the superclass OnDestroy ... gee,
413 // like a dtor would.
414 m_pMinButton.Release();
415 m_pMaxButton.Release();
416 m_pPosButton.Release();
417 CPWL_Wnd::OnDestroy();
418}
419
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700420void CPWL_ScrollBar::RePosChildWnd() {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800421 CFX_FloatRect rcClient = GetClientRect();
422 CFX_FloatRect rcMinButton, rcMaxButton;
Dan Sinclair05df0752017-03-14 14:43:42 -0400423 float fBWidth = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424
425 switch (m_sbType) {
426 case SBT_HSCROLL:
427 if (rcClient.right - rcClient.left >
Dan Sinclaira9e28432017-07-05 14:18:14 -0400428 kButtonWidth * 2 + kPosButtonMinWidth + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800429 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400430 rcClient.left + kButtonWidth, rcClient.top);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800431 rcMaxButton =
Dan Sinclaira9e28432017-07-05 14:18:14 -0400432 CFX_FloatRect(rcClient.right - kButtonWidth, rcClient.bottom,
433 rcClient.right, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700434 } else {
Dan Sinclaira9e28432017-07-05 14:18:14 -0400435 fBWidth = (rcClient.right - rcClient.left - kPosButtonMinWidth - 2) / 2;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436
437 if (fBWidth > 0) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800438 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
439 rcClient.left + fBWidth, rcClient.top);
440 rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom,
441 rcClient.right, rcClient.top);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800442 } else {
tsepez4cf55152016-11-02 14:37:54 -0700443 SetVisible(false);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800444 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700445 }
446 break;
447 case SBT_VSCROLL:
448 if (IsFloatBigger(rcClient.top - rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400449 kButtonWidth * 2 + kPosButtonMinWidth + 2)) {
450 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - kButtonWidth,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800451 rcClient.right, rcClient.top);
452 rcMaxButton =
453 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400454 rcClient.bottom + kButtonWidth);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700455 } else {
Dan Sinclaira9e28432017-07-05 14:18:14 -0400456 fBWidth = (rcClient.top - rcClient.bottom - kPosButtonMinWidth - 2) / 2;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700457
458 if (IsFloatBigger(fBWidth, 0)) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800459 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth,
460 rcClient.right, rcClient.top);
461 rcMaxButton =
462 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
463 rcClient.bottom + fBWidth);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800464 } else {
tsepez4cf55152016-11-02 14:37:54 -0700465 SetVisible(false);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800466 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700467 }
468 break;
469 }
470
471 if (m_pMinButton)
tsepez4cf55152016-11-02 14:37:54 -0700472 m_pMinButton->Move(rcMinButton, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 if (m_pMaxButton)
tsepez4cf55152016-11-02 14:37:54 -0700474 m_pMaxButton->Move(rcMaxButton, true, false);
475 MovePosButton(false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700476}
477
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400478void CPWL_ScrollBar::GetThisAppearanceStream(std::ostringstream* psAppStream) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800479 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700480
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400481 if (!IsVisible() || rectWnd.IsEmpty())
482 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700483
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -0400484 *psAppStream << "q\n"
485 << "0 w\n"
486 << CPWL_Utils::GetColorAppStream(GetBackgroundColor(), true)
487 << rectWnd.left << " " << rectWnd.bottom << " "
488 << rectWnd.right - rectWnd.left << " "
489 << rectWnd.top - rectWnd.bottom << " re b Q\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700490}
491
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700492void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800493 CFX_Matrix* pUser2Device) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800494 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495
496 if (IsVisible() && !rectWnd.IsEmpty()) {
497 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rectWnd,
498 GetBackgroundColor(), GetTransparency());
499
500 CPWL_Utils::DrawStrokeLine(
501 pDevice, pUser2Device,
Dan Sinclairf528eee2017-02-14 11:52:07 -0500502 CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f),
503 CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700504 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
505
506 CPWL_Utils::DrawStrokeLine(
507 pDevice, pUser2Device,
Dan Sinclairf528eee2017-02-14 11:52:07 -0500508 CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f),
509 CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700510 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
511 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700512}
513
Dan Sinclairf528eee2017-02-14 11:52:07 -0500514bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700516
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 if (HasFlag(PWS_AUTOTRANSPARENT)) {
518 if (GetTransparency() != 255) {
519 SetTransparency(255);
520 InvalidateRect();
521 }
522 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700523
Tom Sepez281a9ea2016-02-26 14:24:28 -0800524 CFX_FloatRect rcMinArea, rcMaxArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700525
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700526 if (m_pPosButton && m_pPosButton->IsVisible()) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800527 CFX_FloatRect rcClient = GetClientRect();
528 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
Lei Zhang60f507b2015-06-13 00:41:00 -0700529
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530 switch (m_sbType) {
531 case SBT_HSCROLL:
Dan Sinclaira9e28432017-07-05 14:18:14 -0400532 rcMinArea = CFX_FloatRect(rcClient.left + kButtonWidth, rcClient.bottom,
533 rcPosButton.left, rcClient.top);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800534 rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400535 rcClient.right - kButtonWidth, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536
537 break;
538 case SBT_VSCROLL:
Dan Sinclaira9e28432017-07-05 14:18:14 -0400539 rcMinArea = CFX_FloatRect(rcClient.left, rcPosButton.top,
540 rcClient.right, rcClient.top - kButtonWidth);
541 rcMaxArea = CFX_FloatRect(rcClient.left, rcClient.bottom + kButtonWidth,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800542 rcClient.right, rcPosButton.bottom);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700543 break;
544 }
545
546 rcMinArea.Normalize();
547 rcMaxArea.Normalize();
548
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500549 if (rcMinArea.Contains(point)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700550 m_sData.SubBig();
tsepez4cf55152016-11-02 14:37:54 -0700551 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700552 NotifyScrollWindow();
553 }
554
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500555 if (rcMaxArea.Contains(point)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700556 m_sData.AddBig();
tsepez4cf55152016-11-02 14:37:54 -0700557 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700558 NotifyScrollWindow();
559 }
560 }
561
tsepez4cf55152016-11-02 14:37:54 -0700562 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700563}
564
Dan Sinclairf528eee2017-02-14 11:52:07 -0500565bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700566 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700567
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 if (HasFlag(PWS_AUTOTRANSPARENT)) {
Dan Sinclairfc54e052017-02-23 09:59:05 -0500569 if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) {
570 SetTransparency(PWL_SCROLLBAR_TRANSPARENCY);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700571 InvalidateRect();
572 }
573 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700574
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700575 EndTimer();
tsepez4cf55152016-11-02 14:37:54 -0700576 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700577
tsepez4cf55152016-11-02 14:37:54 -0700578 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700579}
580
Dan Sinclairfb00ec22017-07-05 09:28:15 -0400581void CPWL_ScrollBar::SetScrollInfo(const PWL_SCROLL_INFO& info) {
582 if (info == m_OriginInfo)
583 return;
584
585 m_OriginInfo = info;
586 float fMax =
587 std::max(0.0f, info.fContentMax - info.fContentMin - info.fPlateWidth);
588 SetScrollRange(0, fMax, info.fPlateWidth);
589 SetScrollStep(info.fBigStep, info.fSmallStep);
590}
591
Dan Sinclair7e0336e2017-07-05 09:39:50 -0400592void CPWL_ScrollBar::SetScrollPosition(float pos) {
593 switch (m_sbType) {
594 case SBT_HSCROLL:
595 pos = pos - m_OriginInfo.fContentMin;
596 break;
597 case SBT_VSCROLL:
598 pos = m_OriginInfo.fContentMax - pos;
599 break;
600 }
601 SetScrollPos(pos);
602}
603
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400604void CPWL_ScrollBar::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
605 if (child == m_pMinButton)
606 OnMinButtonLBDown(pos);
607 else if (child == m_pMaxButton)
608 OnMaxButtonLBDown(pos);
609 else if (child == m_pPosButton)
610 OnPosButtonLBDown(pos);
611}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700612
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400613void CPWL_ScrollBar::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
614 if (child == m_pMinButton)
615 OnMinButtonLBUp(pos);
616 else if (child == m_pMaxButton)
617 OnMaxButtonLBUp(pos);
618 else if (child == m_pPosButton)
619 OnPosButtonLBUp(pos);
620}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700621
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400622void CPWL_ScrollBar::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {
623 if (child == m_pMinButton)
624 OnMinButtonMouseMove(pos);
625 else if (child == m_pMaxButton)
626 OnMaxButtonMouseMove(pos);
627 else if (child == m_pPosButton)
628 OnPosButtonMouseMove(pos);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700629}
630
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700631void CPWL_ScrollBar::CreateButtons(const PWL_CREATEPARAM& cp) {
632 PWL_CREATEPARAM scp = cp;
633 scp.pParentWnd = this;
634 scp.dwBorderWidth = 2;
dsinclair92cb5e52016-05-16 11:38:28 -0700635 scp.nBorderStyle = BorderStyle::BEVELED;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700636
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700637 scp.dwFlags =
638 PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700639
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700640 if (!m_pMinButton) {
641 m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN);
642 m_pMinButton->Create(scp);
643 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700644
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700645 if (!m_pMaxButton) {
646 m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX);
647 m_pMaxButton->Create(scp);
648 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700649
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650 if (!m_pPosButton) {
651 m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS);
tsepez4cf55152016-11-02 14:37:54 -0700652 m_pPosButton->SetVisible(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700653 m_pPosButton->Create(scp);
654 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700655}
656
Dan Sinclair05df0752017-03-14 14:43:42 -0400657float CPWL_ScrollBar::GetScrollBarWidth() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700658 if (!IsVisible())
659 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700660
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700661 return PWL_SCROLLBAR_WIDTH;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700662}
663
Dan Sinclair05df0752017-03-14 14:43:42 -0400664void CPWL_ScrollBar::SetScrollRange(float fMin,
665 float fMax,
666 float fClientWidth) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700667 if (m_pPosButton) {
668 m_sData.SetScrollRange(fMin, fMax);
669 m_sData.SetClientWidth(fClientWidth);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700670
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700671 if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
tsepez4cf55152016-11-02 14:37:54 -0700672 m_pPosButton->SetVisible(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700673 } else {
tsepez4cf55152016-11-02 14:37:54 -0700674 m_pPosButton->SetVisible(true);
675 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700676 }
677 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700678}
679
Dan Sinclair05df0752017-03-14 14:43:42 -0400680void CPWL_ScrollBar::SetScrollPos(float fPos) {
681 float fOldPos = m_sData.fScrollPos;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700682 m_sData.SetPos(fPos);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700683 if (!IsFloatEqual(m_sData.fScrollPos, fOldPos))
tsepez4cf55152016-11-02 14:37:54 -0700684 MovePosButton(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700685}
686
Dan Sinclair05df0752017-03-14 14:43:42 -0400687void CPWL_ScrollBar::SetScrollStep(float fBigStep, float fSmallStep) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688 m_sData.SetBigStep(fBigStep);
689 m_sData.SetSmallStep(fSmallStep);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700690}
691
tsepez4cf55152016-11-02 14:37:54 -0700692void CPWL_ScrollBar::MovePosButton(bool bRefresh) {
Lei Zhang96660d62015-12-14 18:27:25 -0800693 ASSERT(m_pMinButton);
694 ASSERT(m_pMaxButton);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700695
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700696 if (m_pPosButton->IsVisible()) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800697 CFX_FloatRect rcClient;
698 CFX_FloatRect rcPosArea, rcPosButton;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700699
700 rcClient = GetClientRect();
701 rcPosArea = GetScrollArea();
702
Dan Sinclair05df0752017-03-14 14:43:42 -0400703 float fLeft, fRight, fTop, fBottom;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700704
705 switch (m_sbType) {
706 case SBT_HSCROLL:
707 fLeft = TrueToFace(m_sData.fScrollPos);
708 fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
709
Dan Sinclaira9e28432017-07-05 14:18:14 -0400710 if (fRight - fLeft < kPosButtonMinWidth)
711 fRight = fLeft + kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700712
713 if (fRight > rcPosArea.right) {
714 fRight = rcPosArea.right;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400715 fLeft = fRight - kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700716 }
717
Tom Sepez281a9ea2016-02-26 14:24:28 -0800718 rcPosButton =
719 CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700720
721 break;
722 case SBT_VSCROLL:
723 fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
724 fTop = TrueToFace(m_sData.fScrollPos);
725
Dan Sinclaira9e28432017-07-05 14:18:14 -0400726 if (IsFloatSmaller(fTop - fBottom, kPosButtonMinWidth))
727 fBottom = fTop - kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700728
729 if (IsFloatSmaller(fBottom, rcPosArea.bottom)) {
730 fBottom = rcPosArea.bottom;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400731 fTop = fBottom + kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700732 }
733
Tom Sepez281a9ea2016-02-26 14:24:28 -0800734 rcPosButton =
735 CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700736
737 break;
738 }
739
tsepez4cf55152016-11-02 14:37:54 -0700740 m_pPosButton->Move(rcPosButton, true, bRefresh);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700741 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700742}
743
Dan Sinclairf528eee2017-02-14 11:52:07 -0500744void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700745 m_sData.SubSmall();
tsepez4cf55152016-11-02 14:37:54 -0700746 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700747 NotifyScrollWindow();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700748
tsepez4cf55152016-11-02 14:37:54 -0700749 m_bMinOrMax = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700750
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700751 EndTimer();
752 BeginTimer(100);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700753}
754
Dan Sinclairf528eee2017-02-14 11:52:07 -0500755void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700756
Dan Sinclairf528eee2017-02-14 11:52:07 -0500757void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700758
Dan Sinclairf528eee2017-02-14 11:52:07 -0500759void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700760 m_sData.AddSmall();
tsepez4cf55152016-11-02 14:37:54 -0700761 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700762 NotifyScrollWindow();
763
tsepez4cf55152016-11-02 14:37:54 -0700764 m_bMinOrMax = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700765
766 EndTimer();
767 BeginTimer(100);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700768}
769
Dan Sinclairf528eee2017-02-14 11:52:07 -0500770void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700771
Dan Sinclairf528eee2017-02-14 11:52:07 -0500772void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700773
Dan Sinclairf528eee2017-02-14 11:52:07 -0500774void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) {
tsepez4cf55152016-11-02 14:37:54 -0700775 m_bMouseDown = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700776
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700777 if (m_pPosButton) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800778 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700779
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700780 switch (m_sbType) {
781 case SBT_HSCROLL:
782 m_nOldPos = point.x;
783 m_fOldPosButton = rcPosButton.left;
784 break;
785 case SBT_VSCROLL:
786 m_nOldPos = point.y;
787 m_fOldPosButton = rcPosButton.top;
788 break;
789 }
790 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700791}
792
Dan Sinclairf528eee2017-02-14 11:52:07 -0500793void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700794 if (m_bMouseDown) {
795 if (!m_bNotifyForever)
796 NotifyScrollWindow();
797 }
tsepez4cf55152016-11-02 14:37:54 -0700798 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700799}
800
Dan Sinclairf528eee2017-02-14 11:52:07 -0500801void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400802 float fOldScrollPos = m_sData.fScrollPos;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700803
Dan Sinclair05df0752017-03-14 14:43:42 -0400804 float fNewPos = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700805
806 switch (m_sbType) {
807 case SBT_HSCROLL:
Dan Sinclair669a4182017-04-03 14:51:45 -0400808 if (fabs(point.x - m_nOldPos) < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700809 return;
810 fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos);
811 break;
812 case SBT_VSCROLL:
Dan Sinclair669a4182017-04-03 14:51:45 -0400813 if (fabs(point.y - m_nOldPos) < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700814 return;
815 fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos);
816 break;
817 }
818
819 if (m_bMouseDown) {
820 switch (m_sbType) {
821 case SBT_HSCROLL:
822
823 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
824 fNewPos = m_sData.ScrollRange.fMin;
825 }
826
827 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
828 fNewPos = m_sData.ScrollRange.fMax;
829 }
830
831 m_sData.SetPos(fNewPos);
832
833 break;
834 case SBT_VSCROLL:
835
836 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
837 fNewPos = m_sData.ScrollRange.fMin;
838 }
839
840 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
841 fNewPos = m_sData.ScrollRange.fMax;
842 }
843
844 m_sData.SetPos(fNewPos);
845
846 break;
847 }
848
849 if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) {
tsepez4cf55152016-11-02 14:37:54 -0700850 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700851
852 if (m_bNotifyForever)
853 NotifyScrollWindow();
854 }
855 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700856}
857
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700858void CPWL_ScrollBar::NotifyScrollWindow() {
Dan Sinclair63fbd8d2017-07-05 14:10:36 -0400859 CPWL_Wnd* pParent = GetParentWindow();
860 if (!pParent || m_sbType != SBT_VSCROLL)
861 return;
862
863 pParent->ScrollWindowVertically(m_OriginInfo.fContentMax -
864 m_sData.fScrollPos);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700865}
866
Tom Sepez281a9ea2016-02-26 14:24:28 -0800867CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const {
868 CFX_FloatRect rcClient = GetClientRect();
869 CFX_FloatRect rcArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700870
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700871 if (!m_pMinButton || !m_pMaxButton)
872 return rcClient;
Lei Zhang60f507b2015-06-13 00:41:00 -0700873
Tom Sepez281a9ea2016-02-26 14:24:28 -0800874 CFX_FloatRect rcMin = m_pMinButton->GetWindowRect();
875 CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700876
Dan Sinclair05df0752017-03-14 14:43:42 -0400877 float fMinWidth = rcMin.right - rcMin.left;
878 float fMinHeight = rcMin.top - rcMin.bottom;
879 float fMaxWidth = rcMax.right - rcMax.left;
880 float fMaxHeight = rcMax.top - rcMax.bottom;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700881
882 switch (m_sbType) {
883 case SBT_HSCROLL:
884 if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800885 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
886 rcClient.right - fMaxWidth - 1, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700887 } else {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800888 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
889 rcClient.left + fMinWidth + 1, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700890 }
891 break;
892 case SBT_VSCROLL:
893 if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800894 rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
895 rcClient.right, rcClient.top - fMaxHeight - 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700896 } else {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800897 rcArea =
898 CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
899 rcClient.right, rcClient.bottom + fMinHeight + 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700900 }
901 break;
902 }
903
904 rcArea.Normalize();
905
906 return rcArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700907}
908
Dan Sinclair05df0752017-03-14 14:43:42 -0400909float CPWL_ScrollBar::TrueToFace(float fTrue) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800910 CFX_FloatRect rcPosArea;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700911 rcPosArea = GetScrollArea();
912
Dan Sinclair05df0752017-03-14 14:43:42 -0400913 float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700914 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
915
Dan Sinclair05df0752017-03-14 14:43:42 -0400916 float fFace = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700917
918 switch (m_sbType) {
919 case SBT_HSCROLL:
920 fFace = rcPosArea.left +
921 fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth;
922 break;
923 case SBT_VSCROLL:
924 fFace = rcPosArea.top -
925 fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth;
926 break;
927 }
928
929 return fFace;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700930}
931
Dan Sinclair05df0752017-03-14 14:43:42 -0400932float CPWL_ScrollBar::FaceToTrue(float fFace) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800933 CFX_FloatRect rcPosArea;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700934 rcPosArea = GetScrollArea();
935
Dan Sinclair05df0752017-03-14 14:43:42 -0400936 float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700937 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
938
Dan Sinclair05df0752017-03-14 14:43:42 -0400939 float fTrue = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700940
941 switch (m_sbType) {
942 case SBT_HSCROLL:
943 fTrue = (fFace - rcPosArea.left) * fFactWidth /
944 (rcPosArea.right - rcPosArea.left);
945 break;
946 case SBT_VSCROLL:
947 fTrue = (rcPosArea.top - fFace) * fFactWidth /
948 (rcPosArea.top - rcPosArea.bottom);
949 break;
950 }
951
952 return fTrue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700953}
954
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700955void CPWL_ScrollBar::CreateChildWnd(const PWL_CREATEPARAM& cp) {
956 CreateButtons(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700957}
958
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700959void CPWL_ScrollBar::TimerProc() {
960 PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700961 if (m_bMinOrMax)
962 m_sData.SubSmall();
963 else
964 m_sData.AddSmall();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700965
tsepezf86ca382016-09-13 12:23:30 -0700966 if (sTemp != m_sData) {
tsepez4cf55152016-11-02 14:37:54 -0700967 MovePosButton(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700968 NotifyScrollWindow();
969 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700970}