blob: f5cdc017e28b32679a23bda32351eb4d4971a302 [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
Dan Sinclairc411eb92017-07-25 09:39:30 -04007#include "fpdfsdk/pwl/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>
Tom Sepez9934cc22018-10-05 17:10:40 +000011#include <utility>
Dan Sinclairc0993812017-07-05 17:17:08 -040012#include <vector>
Henrique Nakashimaf1eae2c2017-06-29 11:18:49 -040013
dsinclair74a34fc2016-09-29 16:41:42 -070014#include "core/fxge/cfx_pathdata.h"
15#include "core/fxge/cfx_renderdevice.h"
Dan Sinclairc411eb92017-07-25 09:39:30 -040016#include "fpdfsdk/pwl/cpwl_wnd.h"
Tom Sepez43f012f2019-08-02 16:16:46 +000017#include "third_party/base/ptr_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070018
Dan Sinclaira9e28432017-07-05 14:18:14 -040019namespace {
20
21constexpr float kButtonWidth = 9.0f;
22constexpr float kPosButtonMinWidth = 2.0f;
Lei Zhang27d718e2018-01-18 21:51:17 +000023constexpr float kScrollBarTriangleHalfLength = 2.0f;
Dan Sinclaira9e28432017-07-05 14:18:14 -040024
25} // namespace
26
Dan Sinclair8e7f9322017-10-16 11:35:42 -040027#define PWL_DEFAULT_HEAVYGRAYCOLOR CFX_Color(CFX_Color::kGray, 0.50)
Dan Sinclaira9e28432017-07-05 14:18:14 -040028
Tom Sepez9934cc22018-10-05 17:10:40 +000029void PWL_FLOATRANGE::Reset() {
30 fMin = 0.0f;
31 fMax = 0.0f;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070032}
33
Andrew Weintraubce4e27f2019-06-13 18:49:18 +000034void PWL_FLOATRANGE::Set(float min, float max) {
35 fMin = std::min(min, max);
36 fMax = std::max(min, max);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070037}
38
Dan Sinclair05df0752017-03-14 14:43:42 -040039bool PWL_FLOATRANGE::In(float x) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070040 return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) &&
41 (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070042}
43
Dan Sinclair05df0752017-03-14 14:43:42 -040044float PWL_FLOATRANGE::GetWidth() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070045 return fMax - fMin;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070046}
47
Nico Weber9d8ec5a2015-08-04 13:00:21 -070048PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() {
49 Default();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070050}
51
Nico Weber9d8ec5a2015-08-04 13:00:21 -070052void PWL_SCROLL_PRIVATEDATA::Default() {
Tom Sepez9934cc22018-10-05 17:10:40 +000053 ScrollRange.Reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054 fScrollPos = ScrollRange.fMin;
55 fClientWidth = 0;
56 fBigStep = 10;
57 fSmallStep = 1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070058}
59
Dan Sinclair05df0752017-03-14 14:43:42 -040060void PWL_SCROLL_PRIVATEDATA::SetScrollRange(float min, float max) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070061 ScrollRange.Set(min, max);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070062
Nico Weber9d8ec5a2015-08-04 13:00:21 -070063 if (IsFloatSmaller(fScrollPos, ScrollRange.fMin))
64 fScrollPos = ScrollRange.fMin;
65 if (IsFloatBigger(fScrollPos, ScrollRange.fMax))
66 fScrollPos = ScrollRange.fMax;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070067}
68
Dan Sinclair05df0752017-03-14 14:43:42 -040069void PWL_SCROLL_PRIVATEDATA::SetClientWidth(float width) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070070 fClientWidth = width;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070071}
72
Dan Sinclair05df0752017-03-14 14:43:42 -040073void PWL_SCROLL_PRIVATEDATA::SetSmallStep(float step) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074 fSmallStep = step;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070075}
76
Dan Sinclair05df0752017-03-14 14:43:42 -040077void PWL_SCROLL_PRIVATEDATA::SetBigStep(float step) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070078 fBigStep = step;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070079}
80
Dan Sinclair05df0752017-03-14 14:43:42 -040081bool PWL_SCROLL_PRIVATEDATA::SetPos(float pos) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070082 if (ScrollRange.In(pos)) {
83 fScrollPos = pos;
tsepez4cf55152016-11-02 14:37:54 -070084 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070085 }
tsepez4cf55152016-11-02 14:37:54 -070086 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070087}
88
Nico Weber9d8ec5a2015-08-04 13:00:21 -070089void PWL_SCROLL_PRIVATEDATA::AddSmall() {
90 if (!SetPos(fScrollPos + fSmallStep))
91 SetPos(ScrollRange.fMax);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070092}
93
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094void PWL_SCROLL_PRIVATEDATA::SubSmall() {
95 if (!SetPos(fScrollPos - fSmallStep))
96 SetPos(ScrollRange.fMin);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070097}
98
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099void PWL_SCROLL_PRIVATEDATA::AddBig() {
100 if (!SetPos(fScrollPos + fBigStep))
101 SetPos(ScrollRange.fMax);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700102}
103
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700104void PWL_SCROLL_PRIVATEDATA::SubBig() {
105 if (!SetPos(fScrollPos - fBigStep))
106 SetPos(ScrollRange.fMin);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700107}
108
Tom Sepezb7c4a022018-10-26 23:56:27 +0000109CPWL_SBButton::CPWL_SBButton(const CreateParams& cp,
110 std::unique_ptr<PrivateData> pAttachedData,
Tom Sepez6fe32f82018-10-25 23:25:58 +0000111 PWL_SCROLLBAR_TYPE eScrollBarType,
112 PWL_SBBUTTON_TYPE eButtonType)
Tom Sepezb7c4a022018-10-26 23:56:27 +0000113 : CPWL_Wnd(cp, std::move(pAttachedData)),
Tom Sepez6fe32f82018-10-25 23:25:58 +0000114 m_eScrollBarType(eScrollBarType),
Tom Sepezea08d172018-10-29 17:29:06 +0000115 m_eSBButtonType(eButtonType) {
116 GetCreationParams()->eCursorType = FXCT_ARROW;
117}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700118
Tom Sepez6fe32f82018-10-25 23:25:58 +0000119CPWL_SBButton::~CPWL_SBButton() = default;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700120
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700121void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
Lei Zhangeb14e042017-08-15 13:56:43 -0700122 const CFX_Matrix& mtUser2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700123 if (!IsVisible())
124 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700125
Tom Sepez281a9ea2016-02-26 14:24:28 -0800126 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700127 if (rectWnd.IsEmpty())
128 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700129
Dan Sinclairf528eee2017-02-14 11:52:07 -0500130 CFX_PointF ptCenter = GetCenterPoint();
Dan Sinclairfc54e052017-02-23 09:59:05 -0500131 int32_t nTransparency = GetTransparency();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700132
Dan Sinclairc0993812017-07-05 17:17:08 -0400133 if (m_eScrollBarType == SBT_HSCROLL) {
Lei Zhangeb14e042017-08-15 13:56:43 -0700134 CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700135
Dan Sinclairc0993812017-07-05 17:17:08 -0400136 CFX_PointF pt1;
137 CFX_PointF pt2;
138 CFX_PointF pt3;
Lei Zhang27d718e2018-01-18 21:51:17 +0000139 static constexpr float kScrollBarTriangleQuarterLength =
140 kScrollBarTriangleHalfLength * 0.5;
Dan Sinclairc0993812017-07-05 17:17:08 -0400141 if (m_eSBButtonType == PSBT_MIN) {
Lei Zhang27d718e2018-01-18 21:51:17 +0000142 pt1 =
143 CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength, ptCenter.y);
144 pt2 = CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength,
145 ptCenter.y + kScrollBarTriangleHalfLength);
146 pt3 = CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength,
147 ptCenter.y - kScrollBarTriangleHalfLength);
Dan Sinclairc0993812017-07-05 17:17:08 -0400148 } else if (m_eSBButtonType == PSBT_MAX) {
Lei Zhang27d718e2018-01-18 21:51:17 +0000149 pt1 =
150 CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength, ptCenter.y);
151 pt2 = CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength,
152 ptCenter.y + kScrollBarTriangleHalfLength);
153 pt3 = CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength,
154 ptCenter.y - kScrollBarTriangleHalfLength);
Dan Sinclairc0993812017-07-05 17:17:08 -0400155 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700156
Lei Zhang27d718e2018-01-18 21:51:17 +0000157 if (rectWnd.right - rectWnd.left > kScrollBarTriangleHalfLength * 2 &&
158 rectWnd.top - rectWnd.bottom > kScrollBarTriangleHalfLength) {
Dan Sinclairc0993812017-07-05 17:17:08 -0400159 CFX_PathData path;
160 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
161 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
162 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
163 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700164
Lei Zhangeb14e042017-08-15 13:56:43 -0700165 pDevice->DrawPath(&path, &mtUser2Device, nullptr,
Dan Sinclairc0993812017-07-05 17:17:08 -0400166 PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency), 0,
167 FXFILL_ALTERNATE);
168 }
169 return;
170 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700171
Dan Sinclairc0993812017-07-05 17:17:08 -0400172 // draw border
Lei Zhange6d45592018-04-12 14:15:33 +0000173 pDevice->DrawStrokeRect(mtUser2Device, rectWnd,
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400174 ArgbEncode(nTransparency, 100, 100, 100), 0.0f);
Lei Zhange6d45592018-04-12 14:15:33 +0000175 pDevice->DrawStrokeRect(mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f),
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400176 ArgbEncode(nTransparency, 255, 255, 255), 1.0f);
Dan Sinclairc0993812017-07-05 17:17:08 -0400177
178 if (m_eSBButtonType != PSBT_POS) {
179 // draw background
Dan Sinclairc0993812017-07-05 17:17:08 -0400180 if (IsEnabled()) {
Lei Zhange6d45592018-04-12 14:15:33 +0000181 pDevice->DrawShadow(mtUser2Device, true, false,
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400182 rectWnd.GetDeflated(1.0f, 1.0f), nTransparency, 80,
183 220);
Dan Sinclairc0993812017-07-05 17:17:08 -0400184 } else {
Lei Zhangeb14e042017-08-15 13:56:43 -0700185 pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(1.0f, 1.0f),
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400186 ArgbEncode(255, 255, 255, 255));
Dan Sinclairc0993812017-07-05 17:17:08 -0400187 }
188
189 // draw arrow
190 if (rectWnd.top - rectWnd.bottom > 6.0f) {
191 float fX = rectWnd.left + 1.5f;
192 float fY = rectWnd.bottom;
193 std::vector<CFX_PointF> pts;
Lei Zhange6d45592018-04-12 14:15:33 +0000194 static constexpr float kOffsetsX[] = {2.5f, 2.5f, 4.5f, 6.5f,
195 6.5f, 4.5f, 2.5f};
196 static constexpr float kOffsetsY[] = {5.0f, 6.0f, 4.0f, 6.0f,
197 5.0f, 3.0f, 5.0f};
198 static constexpr float kOffsetsMinY[] = {4.0f, 3.0f, 5.0f, 3.0f,
199 4.0f, 6.0f, 4.0f};
200 static_assert(FX_ArraySize(kOffsetsX) == FX_ArraySize(kOffsetsY),
201 "Wrong offset count");
202 static_assert(FX_ArraySize(kOffsetsX) == FX_ArraySize(kOffsetsMinY),
203 "Wrong offset count");
204 const float* pOffsetsY =
205 m_eSBButtonType == PSBT_MIN ? kOffsetsMinY : kOffsetsY;
206 for (size_t i = 0; i < FX_ArraySize(kOffsetsX); ++i)
207 pts.push_back(CFX_PointF(fX + kOffsetsX[i], fY + pOffsetsY[i]));
208 pDevice->DrawFillArea(mtUser2Device, pts,
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400209 IsEnabled()
210 ? ArgbEncode(nTransparency, 255, 255, 255)
211 : PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
Dan Sinclairc0993812017-07-05 17:17:08 -0400212 }
213 return;
214 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700215
Dan Sinclairc0993812017-07-05 17:17:08 -0400216 if (IsEnabled()) {
217 // draw shadow effect
218 CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
219 CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700220
Dan Sinclairc0993812017-07-05 17:17:08 -0400221 ptTop.x += 1.5f;
222 ptBottom.x += 1.5f;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700223
Dan Sinclairc0993812017-07-05 17:17:08 -0400224 const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210),
225 ArgbEncode(nTransparency, 220, 220, 220),
226 ArgbEncode(nTransparency, 240, 240, 240),
227 ArgbEncode(nTransparency, 240, 240, 240),
228 ArgbEncode(nTransparency, 210, 210, 210),
229 ArgbEncode(nTransparency, 180, 180, 180),
230 ArgbEncode(nTransparency, 150, 150, 150),
231 ArgbEncode(nTransparency, 150, 150, 150),
232 ArgbEncode(nTransparency, 180, 180, 180),
233 ArgbEncode(nTransparency, 210, 210, 210)};
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400234 for (FX_COLORREF ref : refs) {
Lei Zhangeb14e042017-08-15 13:56:43 -0700235 pDevice->DrawStrokeLine(&mtUser2Device, ptTop, ptBottom, ref, 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236
Dan Sinclairc0993812017-07-05 17:17:08 -0400237 ptTop.x += 1.0f;
238 ptBottom.x += 1.0f;
239 }
240 } else {
Lei Zhangeb14e042017-08-15 13:56:43 -0700241 pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f),
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400242 ArgbEncode(255, 255, 255, 255));
Dan Sinclairc0993812017-07-05 17:17:08 -0400243 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700244
Dan Sinclairc0993812017-07-05 17:17:08 -0400245 // draw friction
246 if (rectWnd.Height() <= 8.0f)
247 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700248
Dan Sinclairc0993812017-07-05 17:17:08 -0400249 FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
250 if (!IsEnabled())
251 crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700252
Dan Sinclairc0993812017-07-05 17:17:08 -0400253 float nFrictionWidth = 5.0f;
254 float nFrictionHeight = 5.5f;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255
Dan Sinclairc0993812017-07-05 17:17:08 -0400256 CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
257 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
258 CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
259 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260
Dan Sinclairc0993812017-07-05 17:17:08 -0400261 for (size_t i = 0; i < 3; ++i) {
Lei Zhangeb14e042017-08-15 13:56:43 -0700262 pDevice->DrawStrokeLine(&mtUser2Device, ptLeft, ptRight, crStroke, 1.0f);
Dan Sinclairc0993812017-07-05 17:17:08 -0400263 ptLeft.y += 2.0f;
264 ptRight.y += 2.0f;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700265 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700266}
267
Dan Sinclairf528eee2017-02-14 11:52:07 -0500268bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700269 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400272 pParent->NotifyLButtonDown(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700273
tsepez4cf55152016-11-02 14:37:54 -0700274 m_bMouseDown = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700275 SetCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700276
tsepez4cf55152016-11-02 14:37:54 -0700277 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700278}
279
Dan Sinclairf528eee2017-02-14 11:52:07 -0500280bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700281 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700282
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 if (CPWL_Wnd* pParent = GetParentWindow())
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400284 pParent->NotifyLButtonUp(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700285
tsepez4cf55152016-11-02 14:37:54 -0700286 m_bMouseDown = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700287 ReleaseCapture();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700288
tsepez4cf55152016-11-02 14:37:54 -0700289 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700290}
291
Dan Sinclairf528eee2017-02-14 11:52:07 -0500292bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700293 CPWL_Wnd::OnMouseMove(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700294
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400295 if (CPWL_Wnd* pParent = GetParentWindow())
296 pParent->NotifyMouseMove(this, point);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700297
tsepez4cf55152016-11-02 14:37:54 -0700298 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700299}
300
Tom Sepezb7c4a022018-10-26 23:56:27 +0000301CPWL_ScrollBar::CPWL_ScrollBar(const CreateParams& cp,
302 std::unique_ptr<PrivateData> pAttachedData,
Tom Sepez6fe32f82018-10-25 23:25:58 +0000303 PWL_SCROLLBAR_TYPE sbType)
Tom Sepezea08d172018-10-29 17:29:06 +0000304 : CPWL_Wnd(cp, std::move(pAttachedData)), m_sbType(sbType) {
305 GetCreationParams()->eCursorType = FXCT_ARROW;
306}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700307
Tom Sepez6fe32f82018-10-25 23:25:58 +0000308CPWL_ScrollBar::~CPWL_ScrollBar() = default;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700309
Tom Sepez5e042a12017-05-30 14:13:44 -0700310void CPWL_ScrollBar::OnDestroy() {
311 // Until cleanup takes place in the virtual destructor for CPWL_Wnd
312 // subclasses, implement the virtual OnDestroy method that does the
313 // cleanup first, then invokes the superclass OnDestroy ... gee,
314 // like a dtor would.
315 m_pMinButton.Release();
316 m_pMaxButton.Release();
317 m_pPosButton.Release();
318 CPWL_Wnd::OnDestroy();
319}
320
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400321bool CPWL_ScrollBar::RePosChildWnd() {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800322 CFX_FloatRect rcClient = GetClientRect();
323 CFX_FloatRect rcMinButton, rcMaxButton;
Dan Sinclair05df0752017-03-14 14:43:42 -0400324 float fBWidth = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325
326 switch (m_sbType) {
327 case SBT_HSCROLL:
328 if (rcClient.right - rcClient.left >
Dan Sinclaira9e28432017-07-05 14:18:14 -0400329 kButtonWidth * 2 + kPosButtonMinWidth + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800330 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400331 rcClient.left + kButtonWidth, rcClient.top);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800332 rcMaxButton =
Dan Sinclaira9e28432017-07-05 14:18:14 -0400333 CFX_FloatRect(rcClient.right - kButtonWidth, rcClient.bottom,
334 rcClient.right, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700335 } else {
Dan Sinclaira9e28432017-07-05 14:18:14 -0400336 fBWidth = (rcClient.right - rcClient.left - kPosButtonMinWidth - 2) / 2;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700337
338 if (fBWidth > 0) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800339 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
340 rcClient.left + fBWidth, rcClient.top);
341 rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom,
342 rcClient.right, rcClient.top);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800343 } else {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400344 if (!SetVisible(false))
345 return false;
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800346 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700347 }
348 break;
349 case SBT_VSCROLL:
350 if (IsFloatBigger(rcClient.top - rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400351 kButtonWidth * 2 + kPosButtonMinWidth + 2)) {
352 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - kButtonWidth,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800353 rcClient.right, rcClient.top);
354 rcMaxButton =
355 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400356 rcClient.bottom + kButtonWidth);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357 } else {
Dan Sinclaira9e28432017-07-05 14:18:14 -0400358 fBWidth = (rcClient.top - rcClient.bottom - kPosButtonMinWidth - 2) / 2;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700359
360 if (IsFloatBigger(fBWidth, 0)) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800361 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth,
362 rcClient.right, rcClient.top);
363 rcMaxButton =
364 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
365 rcClient.bottom + fBWidth);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800366 } else {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400367 if (!SetVisible(false))
368 return false;
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800369 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 }
371 break;
372 }
373
Tom Sepezd8ae8f82019-06-12 17:58:33 +0000374 ObservedPtr<CPWL_ScrollBar> thisObserved(this);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400375 if (m_pMinButton) {
tsepez4cf55152016-11-02 14:37:54 -0700376 m_pMinButton->Move(rcMinButton, true, false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400377 if (!thisObserved)
378 return false;
379 }
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400380 if (m_pMaxButton) {
tsepez4cf55152016-11-02 14:37:54 -0700381 m_pMaxButton->Move(rcMaxButton, true, false);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400382 if (!thisObserved)
383 return false;
384 }
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400385 if (!MovePosButton(false))
386 return false;
387
388 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700389}
390
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700391void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice,
Lei Zhangeb14e042017-08-15 13:56:43 -0700392 const CFX_Matrix& mtUser2Device) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800393 CFX_FloatRect rectWnd = GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394
395 if (IsVisible() && !rectWnd.IsEmpty()) {
Lei Zhangeb14e042017-08-15 13:56:43 -0700396 pDevice->DrawFillRect(&mtUser2Device, rectWnd, GetBackgroundColor(),
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400397 GetTransparency());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400399 pDevice->DrawStrokeLine(
Lei Zhangeb14e042017-08-15 13:56:43 -0700400 &mtUser2Device, CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f),
Dan Sinclairf528eee2017-02-14 11:52:07 -0500401 CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
403
Dan Sinclair0b7378a2017-07-17 12:05:40 -0400404 pDevice->DrawStrokeLine(
Lei Zhangeb14e042017-08-15 13:56:43 -0700405 &mtUser2Device, CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f),
Dan Sinclairf528eee2017-02-14 11:52:07 -0500406 CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700407 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
408 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700409}
410
Dan Sinclairf528eee2017-02-14 11:52:07 -0500411bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412 CPWL_Wnd::OnLButtonDown(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700413
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700414 if (HasFlag(PWS_AUTOTRANSPARENT)) {
415 if (GetTransparency() != 255) {
416 SetTransparency(255);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400417 if (!InvalidateRect(nullptr))
418 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419 }
420 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700421
Tom Sepez281a9ea2016-02-26 14:24:28 -0800422 CFX_FloatRect rcMinArea, rcMaxArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700423
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424 if (m_pPosButton && m_pPosButton->IsVisible()) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800425 CFX_FloatRect rcClient = GetClientRect();
426 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
Lei Zhang60f507b2015-06-13 00:41:00 -0700427
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700428 switch (m_sbType) {
429 case SBT_HSCROLL:
Dan Sinclaira9e28432017-07-05 14:18:14 -0400430 rcMinArea = CFX_FloatRect(rcClient.left + kButtonWidth, rcClient.bottom,
431 rcPosButton.left, rcClient.top);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800432 rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom,
Dan Sinclaira9e28432017-07-05 14:18:14 -0400433 rcClient.right - kButtonWidth, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700434
435 break;
436 case SBT_VSCROLL:
Dan Sinclaira9e28432017-07-05 14:18:14 -0400437 rcMinArea = CFX_FloatRect(rcClient.left, rcPosButton.top,
438 rcClient.right, rcClient.top - kButtonWidth);
439 rcMaxArea = CFX_FloatRect(rcClient.left, rcClient.bottom + kButtonWidth,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800440 rcClient.right, rcPosButton.bottom);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700441 break;
442 }
443
444 rcMinArea.Normalize();
445 rcMaxArea.Normalize();
446
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500447 if (rcMinArea.Contains(point)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 m_sData.SubBig();
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400449 if (!MovePosButton(true))
450 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700451 NotifyScrollWindow();
452 }
453
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500454 if (rcMaxArea.Contains(point)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700455 m_sData.AddBig();
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400456 if (!MovePosButton(true))
457 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700458 NotifyScrollWindow();
459 }
460 }
461
tsepez4cf55152016-11-02 14:37:54 -0700462 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700463}
464
Dan Sinclairf528eee2017-02-14 11:52:07 -0500465bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700466 CPWL_Wnd::OnLButtonUp(point, nFlag);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700467
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468 if (HasFlag(PWS_AUTOTRANSPARENT)) {
Dan Sinclairfc54e052017-02-23 09:59:05 -0500469 if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) {
470 SetTransparency(PWL_SCROLLBAR_TRANSPARENCY);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400471 if (!InvalidateRect(nullptr))
472 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 }
474 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700475
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700476 EndTimer();
tsepez4cf55152016-11-02 14:37:54 -0700477 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700478
tsepez4cf55152016-11-02 14:37:54 -0700479 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700480}
481
Dan Sinclairfb00ec22017-07-05 09:28:15 -0400482void CPWL_ScrollBar::SetScrollInfo(const PWL_SCROLL_INFO& info) {
483 if (info == m_OriginInfo)
484 return;
485
486 m_OriginInfo = info;
487 float fMax =
488 std::max(0.0f, info.fContentMax - info.fContentMin - info.fPlateWidth);
489 SetScrollRange(0, fMax, info.fPlateWidth);
490 SetScrollStep(info.fBigStep, info.fSmallStep);
491}
492
Dan Sinclair7e0336e2017-07-05 09:39:50 -0400493void CPWL_ScrollBar::SetScrollPosition(float pos) {
494 switch (m_sbType) {
495 case SBT_HSCROLL:
496 pos = pos - m_OriginInfo.fContentMin;
497 break;
498 case SBT_VSCROLL:
499 pos = m_OriginInfo.fContentMax - pos;
500 break;
501 }
502 SetScrollPos(pos);
503}
504
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400505void CPWL_ScrollBar::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
506 if (child == m_pMinButton)
507 OnMinButtonLBDown(pos);
508 else if (child == m_pMaxButton)
509 OnMaxButtonLBDown(pos);
510 else if (child == m_pPosButton)
511 OnPosButtonLBDown(pos);
512}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700513
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400514void CPWL_ScrollBar::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
515 if (child == m_pMinButton)
516 OnMinButtonLBUp(pos);
517 else if (child == m_pMaxButton)
518 OnMaxButtonLBUp(pos);
519 else if (child == m_pPosButton)
520 OnPosButtonLBUp(pos);
521}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700522
Dan Sinclair7f6bec92017-07-05 14:13:16 -0400523void CPWL_ScrollBar::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {
524 if (child == m_pMinButton)
525 OnMinButtonMouseMove(pos);
526 else if (child == m_pMaxButton)
527 OnMaxButtonMouseMove(pos);
528 else if (child == m_pPosButton)
529 OnPosButtonMouseMove(pos);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700530}
531
Tom Sepezbf157302017-09-15 13:26:32 -0700532void CPWL_ScrollBar::CreateButtons(const CreateParams& cp) {
533 CreateParams scp = cp;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700534 scp.dwBorderWidth = 2;
dsinclair92cb5e52016-05-16 11:38:28 -0700535 scp.nBorderStyle = BorderStyle::BEVELED;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536 scp.dwFlags =
537 PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700538
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700539 if (!m_pMinButton) {
Tom Sepezb7c4a022018-10-26 23:56:27 +0000540 auto pButton = pdfium::MakeUnique<CPWL_SBButton>(scp, CloneAttachedData(),
Tom Sepez9590dee2018-10-26 22:08:43 +0000541 m_sbType, PSBT_MIN);
542 m_pMinButton = pButton.get();
543 AddChild(std::move(pButton));
Tom Sepezb7c4a022018-10-26 23:56:27 +0000544 m_pMinButton->Realize();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700545 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700546
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700547 if (!m_pMaxButton) {
Tom Sepezb7c4a022018-10-26 23:56:27 +0000548 auto pButton = pdfium::MakeUnique<CPWL_SBButton>(scp, CloneAttachedData(),
Tom Sepez9590dee2018-10-26 22:08:43 +0000549 m_sbType, PSBT_MAX);
550 m_pMaxButton = pButton.get();
551 AddChild(std::move(pButton));
Tom Sepezb7c4a022018-10-26 23:56:27 +0000552 m_pMaxButton->Realize();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700553 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700554
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555 if (!m_pPosButton) {
Tom Sepezb7c4a022018-10-26 23:56:27 +0000556 auto pButton = pdfium::MakeUnique<CPWL_SBButton>(scp, CloneAttachedData(),
Tom Sepez9590dee2018-10-26 22:08:43 +0000557 m_sbType, PSBT_POS);
558 m_pPosButton = pButton.get();
Tom Sepezd8ae8f82019-06-12 17:58:33 +0000559 ObservedPtr<CPWL_ScrollBar> thisObserved(this);
Tom Sepez7df950a2018-10-26 19:42:40 +0000560 if (m_pPosButton->SetVisible(false) && thisObserved) {
Tom Sepez9590dee2018-10-26 22:08:43 +0000561 AddChild(std::move(pButton));
Tom Sepezb7c4a022018-10-26 23:56:27 +0000562 m_pPosButton->Realize();
Tom Sepez7df950a2018-10-26 19:42:40 +0000563 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700564 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700565}
566
Dan Sinclair05df0752017-03-14 14:43:42 -0400567float CPWL_ScrollBar::GetScrollBarWidth() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 if (!IsVisible())
569 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700570
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700571 return PWL_SCROLLBAR_WIDTH;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700572}
573
Dan Sinclair05df0752017-03-14 14:43:42 -0400574void CPWL_ScrollBar::SetScrollRange(float fMin,
575 float fMax,
576 float fClientWidth) {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400577 if (!m_pPosButton)
578 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700579
Tom Sepezd8ae8f82019-06-12 17:58:33 +0000580 ObservedPtr<CPWL_ScrollBar> thisObserved(this);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400581 m_sData.SetScrollRange(fMin, fMax);
582 m_sData.SetClientWidth(fClientWidth);
583
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400584 if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
585 m_pPosButton->SetVisible(false);
586 // Note, |this| may no longer be viable at this point. If more work needs
587 // to be done, check thisObserved.
588 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700589 }
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400590
591 if (!m_pPosButton->SetVisible(true) || !thisObserved)
592 return;
593
594 MovePosButton(true);
595 // Note, |this| may no longer be viable at this point. If more work needs
596 // to be done, check the return value of MovePosButton().
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700597}
598
Dan Sinclair05df0752017-03-14 14:43:42 -0400599void CPWL_ScrollBar::SetScrollPos(float fPos) {
600 float fOldPos = m_sData.fScrollPos;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700601 m_sData.SetPos(fPos);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400602 if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) {
tsepez4cf55152016-11-02 14:37:54 -0700603 MovePosButton(true);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400604 // Note, |this| may no longer be viable at this point. If more work needs
605 // to be done, check the return value of MovePosButton().
606 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700607}
608
Dan Sinclair05df0752017-03-14 14:43:42 -0400609void CPWL_ScrollBar::SetScrollStep(float fBigStep, float fSmallStep) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700610 m_sData.SetBigStep(fBigStep);
611 m_sData.SetSmallStep(fSmallStep);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700612}
613
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400614bool CPWL_ScrollBar::MovePosButton(bool bRefresh) {
Lei Zhang96660d62015-12-14 18:27:25 -0800615 ASSERT(m_pMinButton);
616 ASSERT(m_pMaxButton);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700617
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700618 if (m_pPosButton->IsVisible()) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800619 CFX_FloatRect rcClient;
620 CFX_FloatRect rcPosArea, rcPosButton;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700621
622 rcClient = GetClientRect();
623 rcPosArea = GetScrollArea();
624
Dan Sinclair05df0752017-03-14 14:43:42 -0400625 float fLeft, fRight, fTop, fBottom;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700626
627 switch (m_sbType) {
628 case SBT_HSCROLL:
629 fLeft = TrueToFace(m_sData.fScrollPos);
630 fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
631
Dan Sinclaira9e28432017-07-05 14:18:14 -0400632 if (fRight - fLeft < kPosButtonMinWidth)
633 fRight = fLeft + kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700634
635 if (fRight > rcPosArea.right) {
636 fRight = rcPosArea.right;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400637 fLeft = fRight - kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700638 }
639
Tom Sepez281a9ea2016-02-26 14:24:28 -0800640 rcPosButton =
641 CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700642
643 break;
644 case SBT_VSCROLL:
645 fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
646 fTop = TrueToFace(m_sData.fScrollPos);
647
Dan Sinclaira9e28432017-07-05 14:18:14 -0400648 if (IsFloatSmaller(fTop - fBottom, kPosButtonMinWidth))
649 fBottom = fTop - kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650
651 if (IsFloatSmaller(fBottom, rcPosArea.bottom)) {
652 fBottom = rcPosArea.bottom;
Dan Sinclaira9e28432017-07-05 14:18:14 -0400653 fTop = fBottom + kPosButtonMinWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700654 }
655
Tom Sepez281a9ea2016-02-26 14:24:28 -0800656 rcPosButton =
657 CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700658
659 break;
660 }
661
Tom Sepezd8ae8f82019-06-12 17:58:33 +0000662 ObservedPtr<CPWL_ScrollBar> thisObserved(this);
tsepez4cf55152016-11-02 14:37:54 -0700663 m_pPosButton->Move(rcPosButton, true, bRefresh);
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400664 if (!thisObserved)
665 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700666 }
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400667
668 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700669}
670
Dan Sinclairf528eee2017-02-14 11:52:07 -0500671void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700672 m_sData.SubSmall();
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400673 if (!MovePosButton(true))
674 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700675 NotifyScrollWindow();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700676
tsepez4cf55152016-11-02 14:37:54 -0700677 m_bMinOrMax = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700678
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700679 EndTimer();
680 BeginTimer(100);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700681}
682
Dan Sinclairf528eee2017-02-14 11:52:07 -0500683void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700684
Dan Sinclairf528eee2017-02-14 11:52:07 -0500685void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700686
Dan Sinclairf528eee2017-02-14 11:52:07 -0500687void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688 m_sData.AddSmall();
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400689 if (!MovePosButton(true))
690 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700691 NotifyScrollWindow();
692
tsepez4cf55152016-11-02 14:37:54 -0700693 m_bMinOrMax = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700694
695 EndTimer();
696 BeginTimer(100);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700697}
698
Dan Sinclairf528eee2017-02-14 11:52:07 -0500699void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700700
Dan Sinclairf528eee2017-02-14 11:52:07 -0500701void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700702
Dan Sinclairf528eee2017-02-14 11:52:07 -0500703void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) {
tsepez4cf55152016-11-02 14:37:54 -0700704 m_bMouseDown = true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700705
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700706 if (m_pPosButton) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800707 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700708
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700709 switch (m_sbType) {
710 case SBT_HSCROLL:
711 m_nOldPos = point.x;
712 m_fOldPosButton = rcPosButton.left;
713 break;
714 case SBT_VSCROLL:
715 m_nOldPos = point.y;
716 m_fOldPosButton = rcPosButton.top;
717 break;
718 }
719 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700720}
721
Dan Sinclairf528eee2017-02-14 11:52:07 -0500722void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700723 if (m_bMouseDown) {
724 if (!m_bNotifyForever)
725 NotifyScrollWindow();
726 }
tsepez4cf55152016-11-02 14:37:54 -0700727 m_bMouseDown = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700728}
729
Dan Sinclairf528eee2017-02-14 11:52:07 -0500730void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400731 float fOldScrollPos = m_sData.fScrollPos;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700732
Dan Sinclair05df0752017-03-14 14:43:42 -0400733 float fNewPos = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700734
735 switch (m_sbType) {
736 case SBT_HSCROLL:
Dan Sinclair669a4182017-04-03 14:51:45 -0400737 if (fabs(point.x - m_nOldPos) < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700738 return;
739 fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos);
740 break;
741 case SBT_VSCROLL:
Dan Sinclair669a4182017-04-03 14:51:45 -0400742 if (fabs(point.y - m_nOldPos) < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700743 return;
744 fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos);
745 break;
746 }
747
748 if (m_bMouseDown) {
749 switch (m_sbType) {
750 case SBT_HSCROLL:
751
752 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
753 fNewPos = m_sData.ScrollRange.fMin;
754 }
755
756 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
757 fNewPos = m_sData.ScrollRange.fMax;
758 }
759
760 m_sData.SetPos(fNewPos);
761
762 break;
763 case SBT_VSCROLL:
764
765 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
766 fNewPos = m_sData.ScrollRange.fMin;
767 }
768
769 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
770 fNewPos = m_sData.ScrollRange.fMax;
771 }
772
773 m_sData.SetPos(fNewPos);
774
775 break;
776 }
777
778 if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400779 if (!MovePosButton(true))
780 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700781
782 if (m_bNotifyForever)
783 NotifyScrollWindow();
784 }
785 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700786}
787
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700788void CPWL_ScrollBar::NotifyScrollWindow() {
Dan Sinclair63fbd8d2017-07-05 14:10:36 -0400789 CPWL_Wnd* pParent = GetParentWindow();
790 if (!pParent || m_sbType != SBT_VSCROLL)
791 return;
792
793 pParent->ScrollWindowVertically(m_OriginInfo.fContentMax -
794 m_sData.fScrollPos);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700795}
796
Tom Sepez281a9ea2016-02-26 14:24:28 -0800797CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const {
798 CFX_FloatRect rcClient = GetClientRect();
799 CFX_FloatRect rcArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700800
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700801 if (!m_pMinButton || !m_pMaxButton)
802 return rcClient;
Lei Zhang60f507b2015-06-13 00:41:00 -0700803
Tom Sepez281a9ea2016-02-26 14:24:28 -0800804 CFX_FloatRect rcMin = m_pMinButton->GetWindowRect();
805 CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700806
Lei Zhang98758892018-03-15 15:02:22 +0000807 float fMinWidth = rcMin.Width();
808 float fMinHeight = rcMin.Height();
809 float fMaxWidth = rcMax.Width();
810 float fMaxHeight = rcMax.Height();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700811
812 switch (m_sbType) {
813 case SBT_HSCROLL:
814 if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800815 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
816 rcClient.right - fMaxWidth - 1, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700817 } else {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800818 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
819 rcClient.left + fMinWidth + 1, rcClient.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700820 }
821 break;
822 case SBT_VSCROLL:
823 if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800824 rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
825 rcClient.right, rcClient.top - fMaxHeight - 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700826 } else {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800827 rcArea =
828 CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
829 rcClient.right, rcClient.bottom + fMinHeight + 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700830 }
831 break;
832 }
833
834 rcArea.Normalize();
835
836 return rcArea;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700837}
838
Dan Sinclair05df0752017-03-14 14:43:42 -0400839float CPWL_ScrollBar::TrueToFace(float fTrue) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800840 CFX_FloatRect rcPosArea;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700841 rcPosArea = GetScrollArea();
842
Dan Sinclair05df0752017-03-14 14:43:42 -0400843 float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700844 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
845
Dan Sinclair05df0752017-03-14 14:43:42 -0400846 float fFace = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700847
848 switch (m_sbType) {
849 case SBT_HSCROLL:
850 fFace = rcPosArea.left +
851 fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth;
852 break;
853 case SBT_VSCROLL:
854 fFace = rcPosArea.top -
855 fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth;
856 break;
857 }
858
859 return fFace;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700860}
861
Dan Sinclair05df0752017-03-14 14:43:42 -0400862float CPWL_ScrollBar::FaceToTrue(float fFace) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800863 CFX_FloatRect rcPosArea;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700864 rcPosArea = GetScrollArea();
865
Dan Sinclair05df0752017-03-14 14:43:42 -0400866 float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700867 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
868
Dan Sinclair05df0752017-03-14 14:43:42 -0400869 float fTrue = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700870
871 switch (m_sbType) {
872 case SBT_HSCROLL:
873 fTrue = (fFace - rcPosArea.left) * fFactWidth /
874 (rcPosArea.right - rcPosArea.left);
875 break;
876 case SBT_VSCROLL:
877 fTrue = (rcPosArea.top - fFace) * fFactWidth /
878 (rcPosArea.top - rcPosArea.bottom);
879 break;
880 }
881
882 return fTrue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700883}
884
Tom Sepezbf157302017-09-15 13:26:32 -0700885void CPWL_ScrollBar::CreateChildWnd(const CreateParams& cp) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700886 CreateButtons(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700887}
888
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700889void CPWL_ScrollBar::TimerProc() {
890 PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700891 if (m_bMinOrMax)
892 m_sData.SubSmall();
893 else
894 m_sData.AddSmall();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700895
tsepezf86ca382016-09-13 12:23:30 -0700896 if (sTemp != m_sData) {
Henrique Nakashima55469ae2017-10-04 11:08:45 -0400897 if (!MovePosButton(true))
898 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700899 NotifyScrollWindow();
900 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700901}