1 // 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.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
8
9 #include "core/fxge/cfx_pathdata.h"
10 #include "core/fxge/cfx_renderdevice.h"
11 #include "fpdfsdk/pdfwindow/PWL_Utils.h"
12 #include "fpdfsdk/pdfwindow/PWL_Wnd.h"
13
PWL_FLOATRANGE()14 PWL_FLOATRANGE::PWL_FLOATRANGE() {
15 Default();
16 }
17
PWL_FLOATRANGE(FX_FLOAT min,FX_FLOAT max)18 PWL_FLOATRANGE::PWL_FLOATRANGE(FX_FLOAT min, FX_FLOAT max) {
19 Set(min, max);
20 }
21
Default()22 void PWL_FLOATRANGE::Default() {
23 fMin = 0;
24 fMax = 0;
25 }
26
Set(FX_FLOAT min,FX_FLOAT max)27 void PWL_FLOATRANGE::Set(FX_FLOAT min, FX_FLOAT max) {
28 if (min > max) {
29 fMin = max;
30 fMax = min;
31 } else {
32 fMin = min;
33 fMax = max;
34 }
35 }
36
In(FX_FLOAT x) const37 bool PWL_FLOATRANGE::In(FX_FLOAT x) const {
38 return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) &&
39 (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax));
40 }
41
GetWidth() const42 FX_FLOAT PWL_FLOATRANGE::GetWidth() const {
43 return fMax - fMin;
44 }
45
PWL_SCROLL_PRIVATEDATA()46 PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() {
47 Default();
48 }
49
Default()50 void PWL_SCROLL_PRIVATEDATA::Default() {
51 ScrollRange.Default();
52 fScrollPos = ScrollRange.fMin;
53 fClientWidth = 0;
54 fBigStep = 10;
55 fSmallStep = 1;
56 }
57
SetScrollRange(FX_FLOAT min,FX_FLOAT max)58 void PWL_SCROLL_PRIVATEDATA::SetScrollRange(FX_FLOAT min, FX_FLOAT max) {
59 ScrollRange.Set(min, max);
60
61 if (IsFloatSmaller(fScrollPos, ScrollRange.fMin))
62 fScrollPos = ScrollRange.fMin;
63 if (IsFloatBigger(fScrollPos, ScrollRange.fMax))
64 fScrollPos = ScrollRange.fMax;
65 }
66
SetClientWidth(FX_FLOAT width)67 void PWL_SCROLL_PRIVATEDATA::SetClientWidth(FX_FLOAT width) {
68 fClientWidth = width;
69 }
70
SetSmallStep(FX_FLOAT step)71 void PWL_SCROLL_PRIVATEDATA::SetSmallStep(FX_FLOAT step) {
72 fSmallStep = step;
73 }
74
SetBigStep(FX_FLOAT step)75 void PWL_SCROLL_PRIVATEDATA::SetBigStep(FX_FLOAT step) {
76 fBigStep = step;
77 }
78
SetPos(FX_FLOAT pos)79 bool PWL_SCROLL_PRIVATEDATA::SetPos(FX_FLOAT pos) {
80 if (ScrollRange.In(pos)) {
81 fScrollPos = pos;
82 return true;
83 }
84 return false;
85 }
86
AddSmall()87 void PWL_SCROLL_PRIVATEDATA::AddSmall() {
88 if (!SetPos(fScrollPos + fSmallStep))
89 SetPos(ScrollRange.fMax);
90 }
91
SubSmall()92 void PWL_SCROLL_PRIVATEDATA::SubSmall() {
93 if (!SetPos(fScrollPos - fSmallStep))
94 SetPos(ScrollRange.fMin);
95 }
96
AddBig()97 void PWL_SCROLL_PRIVATEDATA::AddBig() {
98 if (!SetPos(fScrollPos + fBigStep))
99 SetPos(ScrollRange.fMax);
100 }
101
SubBig()102 void PWL_SCROLL_PRIVATEDATA::SubBig() {
103 if (!SetPos(fScrollPos - fBigStep))
104 SetPos(ScrollRange.fMin);
105 }
106
CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,PWL_SBBUTTON_TYPE eButtonType)107 CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,
108 PWL_SBBUTTON_TYPE eButtonType) {
109 m_eScrollBarType = eScrollBarType;
110 m_eSBButtonType = eButtonType;
111
112 m_bMouseDown = false;
113 }
114
~CPWL_SBButton()115 CPWL_SBButton::~CPWL_SBButton() {}
116
GetClassName() const117 CFX_ByteString CPWL_SBButton::GetClassName() const {
118 return "CPWL_SBButton";
119 }
120
OnCreate(PWL_CREATEPARAM & cp)121 void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) {
122 cp.eCursorType = FXCT_ARROW;
123 }
124
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)125 void CPWL_SBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
126 CPWL_Wnd::GetThisAppearanceStream(sAppStream);
127
128 if (!IsVisible())
129 return;
130
131 CFX_ByteTextBuf sButton;
132
133 CFX_FloatRect rectWnd = GetWindowRect();
134
135 if (rectWnd.IsEmpty())
136 return;
137
138 sAppStream << "q\n";
139
140 CFX_PointF ptCenter = GetCenterPoint();
141
142 switch (m_eScrollBarType) {
143 case SBT_HSCROLL:
144 switch (m_eSBButtonType) {
145 case PSBT_MIN: {
146 CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
147 CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
148 ptCenter.y + PWL_TRIANGLE_HALFLEN);
149 CFX_PointF pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
150 ptCenter.y - PWL_TRIANGLE_HALFLEN);
151
152 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
153 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
154 sButton << "0 g\n";
155 sButton << pt1.x << " " << pt1.y << " m\n";
156 sButton << pt2.x << " " << pt2.y << " l\n";
157 sButton << pt3.x << " " << pt3.y << " l\n";
158 sButton << pt1.x << " " << pt1.y << " l f\n";
159
160 sAppStream << sButton;
161 }
162 } break;
163 case PSBT_MAX: {
164 CFX_PointF pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
165 CFX_PointF pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
166 ptCenter.y + PWL_TRIANGLE_HALFLEN);
167 CFX_PointF pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
168 ptCenter.y - PWL_TRIANGLE_HALFLEN);
169
170 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
171 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
172 sButton << "0 g\n";
173 sButton << pt1.x << " " << pt1.y << " m\n";
174 sButton << pt2.x << " " << pt2.y << " l\n";
175 sButton << pt3.x << " " << pt3.y << " l\n";
176 sButton << pt1.x << " " << pt1.y << " l f\n";
177
178 sAppStream << sButton;
179 }
180 } break;
181 default:
182 break;
183 }
184 break;
185 case SBT_VSCROLL:
186 switch (m_eSBButtonType) {
187 case PSBT_MIN: {
188 CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN,
189 ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f);
190 CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN,
191 ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f);
192 CFX_PointF pt3(ptCenter.x, ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f);
193
194 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
195 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
196 sButton << "0 g\n";
197 sButton << pt1.x << " " << pt1.y << " m\n";
198 sButton << pt2.x << " " << pt2.y << " l\n";
199 sButton << pt3.x << " " << pt3.y << " l\n";
200 sButton << pt1.x << " " << pt1.y << " l f\n";
201
202 sAppStream << sButton;
203 }
204 } break;
205 case PSBT_MAX: {
206 CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN,
207 ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f);
208 CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN,
209 ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f);
210 CFX_PointF pt3(ptCenter.x, ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f);
211
212 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
213 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
214 sButton << "0 g\n";
215 sButton << pt1.x << " " << pt1.y << " m\n";
216 sButton << pt2.x << " " << pt2.y << " l\n";
217 sButton << pt3.x << " " << pt3.y << " l\n";
218 sButton << pt1.x << " " << pt1.y << " l f\n";
219
220 sAppStream << sButton;
221 }
222 } break;
223 default:
224 break;
225 }
226 break;
227 default:
228 break;
229 }
230
231 sAppStream << "Q\n";
232 }
233
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)234 void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
235 CFX_Matrix* pUser2Device) {
236 if (!IsVisible())
237 return;
238
239 CFX_FloatRect rectWnd = GetWindowRect();
240 if (rectWnd.IsEmpty())
241 return;
242
243 CFX_PointF ptCenter = GetCenterPoint();
244 int32_t nTransparency = GetTransparency();
245
246 switch (m_eScrollBarType) {
247 case SBT_HSCROLL:
248 CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
249 switch (m_eSBButtonType) {
250 case PSBT_MIN: {
251 CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
252 CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
253 ptCenter.y + PWL_TRIANGLE_HALFLEN);
254 CFX_PointF pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
255 ptCenter.y - PWL_TRIANGLE_HALFLEN);
256
257 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
258 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
259 CFX_PathData path;
260 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
261 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
262 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
263 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
264
265 pDevice->DrawPath(&path, pUser2Device, nullptr,
266 PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency),
267 0, FXFILL_ALTERNATE);
268 }
269 } break;
270 case PSBT_MAX: {
271 CFX_PointF pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
272 CFX_PointF pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
273 ptCenter.y + PWL_TRIANGLE_HALFLEN);
274 CFX_PointF pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
275 ptCenter.y - PWL_TRIANGLE_HALFLEN);
276
277 if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
278 rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
279 CFX_PathData path;
280 path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
281 path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
282 path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
283 path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
284
285 pDevice->DrawPath(&path, pUser2Device, nullptr,
286 PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency),
287 0, FXFILL_ALTERNATE);
288 }
289 } break;
290 default:
291 break;
292 }
293 break;
294 case SBT_VSCROLL:
295 switch (m_eSBButtonType) {
296 case PSBT_MIN: {
297 // draw border
298 CFX_FloatRect rcDraw = rectWnd;
299 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
300 ArgbEncode(nTransparency, 100, 100, 100),
301 0.0f);
302
303 // draw inner border
304 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
305 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
306 ArgbEncode(nTransparency, 255, 255, 255),
307 1.0f);
308
309 // draw background
310
311 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f);
312
313 if (IsEnabled())
314 CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw,
315 nTransparency, 80, 220);
316 else
317 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
318 ArgbEncode(255, 255, 255, 255));
319
320 // draw arrow
321
322 if (rectWnd.top - rectWnd.bottom > 6.0f) {
323 FX_FLOAT fX = rectWnd.left + 1.5f;
324 FX_FLOAT fY = rectWnd.bottom;
325 CFX_PointF pts[7] = {CFX_PointF(fX + 2.5f, fY + 4.0f),
326 CFX_PointF(fX + 2.5f, fY + 3.0f),
327 CFX_PointF(fX + 4.5f, fY + 5.0f),
328 CFX_PointF(fX + 6.5f, fY + 3.0f),
329 CFX_PointF(fX + 6.5f, fY + 4.0f),
330 CFX_PointF(fX + 4.5f, fY + 6.0f),
331 CFX_PointF(fX + 2.5f, fY + 4.0f)};
332
333 if (IsEnabled())
334 CPWL_Utils::DrawFillArea(
335 pDevice, pUser2Device, pts, 7,
336 ArgbEncode(nTransparency, 255, 255, 255));
337 else
338 CPWL_Utils::DrawFillArea(
339 pDevice, pUser2Device, pts, 7,
340 PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
341 }
342 } break;
343 case PSBT_MAX: {
344 // draw border
345 CFX_FloatRect rcDraw = rectWnd;
346 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
347 ArgbEncode(nTransparency, 100, 100, 100),
348 0.0f);
349
350 // draw inner border
351 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
352 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
353 ArgbEncode(nTransparency, 255, 255, 255),
354 1.0f);
355
356 // draw background
357 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f);
358 if (IsEnabled())
359 CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw,
360 nTransparency, 80, 220);
361 else
362 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
363 ArgbEncode(255, 255, 255, 255));
364
365 // draw arrow
366
367 if (rectWnd.top - rectWnd.bottom > 6.0f) {
368 FX_FLOAT fX = rectWnd.left + 1.5f;
369 FX_FLOAT fY = rectWnd.bottom;
370
371 CFX_PointF pts[7] = {CFX_PointF(fX + 2.5f, fY + 5.0f),
372 CFX_PointF(fX + 2.5f, fY + 6.0f),
373 CFX_PointF(fX + 4.5f, fY + 4.0f),
374 CFX_PointF(fX + 6.5f, fY + 6.0f),
375 CFX_PointF(fX + 6.5f, fY + 5.0f),
376 CFX_PointF(fX + 4.5f, fY + 3.0f),
377 CFX_PointF(fX + 2.5f, fY + 5.0f)};
378
379 if (IsEnabled())
380 CPWL_Utils::DrawFillArea(
381 pDevice, pUser2Device, pts, 7,
382 ArgbEncode(nTransparency, 255, 255, 255));
383 else
384 CPWL_Utils::DrawFillArea(
385 pDevice, pUser2Device, pts, 7,
386 PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
387 }
388 } break;
389 case PSBT_POS: {
390 // draw border
391 CFX_FloatRect rcDraw = rectWnd;
392 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
393 ArgbEncode(nTransparency, 100, 100, 100),
394 0.0f);
395
396 // draw inner border
397 rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
398 CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
399 ArgbEncode(nTransparency, 255, 255, 255),
400 1.0f);
401
402 if (IsEnabled()) {
403 // draw shadow effect
404
405 CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
406 CFX_PointF ptBottom =
407 CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
408
409 ptTop.x += 1.5f;
410 ptBottom.x += 1.5f;
411
412 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
413 ArgbEncode(nTransparency, 210, 210, 210),
414 1.0f);
415
416 ptTop.x += 1.0f;
417 ptBottom.x += 1.0f;
418
419 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
420 ArgbEncode(nTransparency, 220, 220, 220),
421 1.0f);
422
423 ptTop.x += 1.0f;
424 ptBottom.x += 1.0f;
425
426 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
427 ArgbEncode(nTransparency, 240, 240, 240),
428 1.0f);
429
430 ptTop.x += 1.0f;
431 ptBottom.x += 1.0f;
432
433 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
434 ArgbEncode(nTransparency, 240, 240, 240),
435 1.0f);
436
437 ptTop.x += 1.0f;
438 ptBottom.x += 1.0f;
439
440 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
441 ArgbEncode(nTransparency, 210, 210, 210),
442 1.0f);
443
444 ptTop.x += 1.0f;
445 ptBottom.x += 1.0f;
446
447 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
448 ArgbEncode(nTransparency, 180, 180, 180),
449 1.0f);
450
451 ptTop.x += 1.0f;
452 ptBottom.x += 1.0f;
453
454 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
455 ArgbEncode(nTransparency, 150, 150, 150),
456 1.0f);
457
458 ptTop.x += 1.0f;
459 ptBottom.x += 1.0f;
460
461 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
462 ArgbEncode(nTransparency, 150, 150, 150),
463 1.0f);
464
465 ptTop.x += 1.0f;
466 ptBottom.x += 1.0f;
467
468 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
469 ArgbEncode(nTransparency, 180, 180, 180),
470 1.0f);
471
472 ptTop.x += 1.0f;
473 ptBottom.x += 1.0f;
474
475 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
476 ArgbEncode(nTransparency, 210, 210, 210),
477 1.0f);
478 } else {
479 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
480 ArgbEncode(255, 255, 255, 255));
481 }
482
483 // draw friction
484
485 if (rectWnd.Height() > 8.0f) {
486 FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
487 if (!IsEnabled())
488 crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255);
489
490 FX_FLOAT nFrictionWidth = 5.0f;
491 FX_FLOAT nFrictionHeight = 5.5f;
492
493 CFX_PointF ptLeft =
494 CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
495 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
496 CFX_PointF ptRight =
497 CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
498 ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
499
500 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight,
501 crStroke, 1.0f);
502
503 ptLeft.y += 2.0f;
504 ptRight.y += 2.0f;
505
506 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight,
507 crStroke, 1.0f);
508
509 ptLeft.y += 2.0f;
510 ptRight.y += 2.0f;
511
512 CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight,
513 crStroke, 1.0f);
514 }
515 } break;
516 default:
517 break;
518 }
519 break;
520 default:
521 break;
522 }
523 }
524
OnLButtonDown(const CFX_PointF & point,uint32_t nFlag)525 bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
526 CPWL_Wnd::OnLButtonDown(point, nFlag);
527
528 if (CPWL_Wnd* pParent = GetParentWindow())
529 pParent->OnNotify(this, PNM_LBUTTONDOWN, 0, (intptr_t)&point);
530
531 m_bMouseDown = true;
532 SetCapture();
533
534 return true;
535 }
536
OnLButtonUp(const CFX_PointF & point,uint32_t nFlag)537 bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
538 CPWL_Wnd::OnLButtonUp(point, nFlag);
539
540 if (CPWL_Wnd* pParent = GetParentWindow())
541 pParent->OnNotify(this, PNM_LBUTTONUP, 0, (intptr_t)&point);
542
543 m_bMouseDown = false;
544 ReleaseCapture();
545
546 return true;
547 }
548
OnMouseMove(const CFX_PointF & point,uint32_t nFlag)549 bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
550 CPWL_Wnd::OnMouseMove(point, nFlag);
551
552 if (CPWL_Wnd* pParent = GetParentWindow()) {
553 pParent->OnNotify(this, PNM_MOUSEMOVE, 0, (intptr_t)&point);
554 }
555
556 return true;
557 }
558
CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)559 CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)
560 : m_sbType(sbType),
561 m_pMinButton(nullptr),
562 m_pMaxButton(nullptr),
563 m_pPosButton(nullptr),
564 m_bMouseDown(false),
565 m_bMinOrMax(false),
566 m_bNotifyForever(true) {}
567
~CPWL_ScrollBar()568 CPWL_ScrollBar::~CPWL_ScrollBar() {}
569
GetClassName() const570 CFX_ByteString CPWL_ScrollBar::GetClassName() const {
571 return "CPWL_ScrollBar";
572 }
573
OnCreate(PWL_CREATEPARAM & cp)574 void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) {
575 cp.eCursorType = FXCT_ARROW;
576 }
577
RePosChildWnd()578 void CPWL_ScrollBar::RePosChildWnd() {
579 CFX_FloatRect rcClient = GetClientRect();
580 CFX_FloatRect rcMinButton, rcMaxButton;
581 FX_FLOAT fBWidth = 0;
582
583 switch (m_sbType) {
584 case SBT_HSCROLL:
585 if (rcClient.right - rcClient.left >
586 PWL_SCROLLBAR_BUTTON_WIDTH * 2 + PWL_SCROLLBAR_POSBUTTON_MINWIDTH +
587 2) {
588 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
589 rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH,
590 rcClient.top);
591 rcMaxButton =
592 CFX_FloatRect(rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH,
593 rcClient.bottom, rcClient.right, rcClient.top);
594 } else {
595 fBWidth = (rcClient.right - rcClient.left -
596 PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) /
597 2;
598
599 if (fBWidth > 0) {
600 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
601 rcClient.left + fBWidth, rcClient.top);
602 rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom,
603 rcClient.right, rcClient.top);
604 } else {
605 SetVisible(false);
606 }
607 }
608 break;
609 case SBT_VSCROLL:
610 if (IsFloatBigger(rcClient.top - rcClient.bottom,
611 PWL_SCROLLBAR_BUTTON_WIDTH * 2 +
612 PWL_SCROLLBAR_POSBUTTON_MINWIDTH + 2)) {
613 rcMinButton = CFX_FloatRect(rcClient.left,
614 rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH,
615 rcClient.right, rcClient.top);
616 rcMaxButton =
617 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
618 rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH);
619 } else {
620 fBWidth = (rcClient.top - rcClient.bottom -
621 PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) /
622 2;
623
624 if (IsFloatBigger(fBWidth, 0)) {
625 rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth,
626 rcClient.right, rcClient.top);
627 rcMaxButton =
628 CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
629 rcClient.bottom + fBWidth);
630 } else {
631 SetVisible(false);
632 }
633 }
634 break;
635 }
636
637 if (m_pMinButton)
638 m_pMinButton->Move(rcMinButton, true, false);
639 if (m_pMaxButton)
640 m_pMaxButton->Move(rcMaxButton, true, false);
641 MovePosButton(false);
642 }
643
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)644 void CPWL_ScrollBar::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
645 CFX_FloatRect rectWnd = GetWindowRect();
646
647 if (IsVisible() && !rectWnd.IsEmpty()) {
648 CFX_ByteTextBuf sButton;
649
650 sButton << "q\n";
651 sButton << "0 w\n"
652 << CPWL_Utils::GetColorAppStream(GetBackgroundColor(), true)
653 .AsStringC();
654 sButton << rectWnd.left << " " << rectWnd.bottom << " "
655 << rectWnd.right - rectWnd.left << " "
656 << rectWnd.top - rectWnd.bottom << " re b Q\n";
657
658 sAppStream << sButton;
659 }
660 }
661
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)662 void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice,
663 CFX_Matrix* pUser2Device) {
664 CFX_FloatRect rectWnd = GetWindowRect();
665
666 if (IsVisible() && !rectWnd.IsEmpty()) {
667 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rectWnd,
668 GetBackgroundColor(), GetTransparency());
669
670 CPWL_Utils::DrawStrokeLine(
671 pDevice, pUser2Device,
672 CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f),
673 CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f),
674 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
675
676 CPWL_Utils::DrawStrokeLine(
677 pDevice, pUser2Device,
678 CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f),
679 CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f),
680 ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
681 }
682 }
683
OnLButtonDown(const CFX_PointF & point,uint32_t nFlag)684 bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
685 CPWL_Wnd::OnLButtonDown(point, nFlag);
686
687 if (HasFlag(PWS_AUTOTRANSPARENT)) {
688 if (GetTransparency() != 255) {
689 SetTransparency(255);
690 InvalidateRect();
691 }
692 }
693
694 CFX_FloatRect rcMinArea, rcMaxArea;
695
696 if (m_pPosButton && m_pPosButton->IsVisible()) {
697 CFX_FloatRect rcClient = GetClientRect();
698 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
699
700 switch (m_sbType) {
701 case SBT_HSCROLL:
702 rcMinArea =
703 CFX_FloatRect(rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH,
704 rcClient.bottom, rcPosButton.left, rcClient.top);
705 rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom,
706 rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH,
707 rcClient.top);
708
709 break;
710 case SBT_VSCROLL:
711 rcMinArea =
712 CFX_FloatRect(rcClient.left, rcPosButton.top, rcClient.right,
713 rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH);
714 rcMaxArea = CFX_FloatRect(rcClient.left,
715 rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH,
716 rcClient.right, rcPosButton.bottom);
717 break;
718 }
719
720 rcMinArea.Normalize();
721 rcMaxArea.Normalize();
722
723 if (rcMinArea.Contains(point)) {
724 m_sData.SubBig();
725 MovePosButton(true);
726 NotifyScrollWindow();
727 }
728
729 if (rcMaxArea.Contains(point)) {
730 m_sData.AddBig();
731 MovePosButton(true);
732 NotifyScrollWindow();
733 }
734 }
735
736 return true;
737 }
738
OnLButtonUp(const CFX_PointF & point,uint32_t nFlag)739 bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
740 CPWL_Wnd::OnLButtonUp(point, nFlag);
741
742 if (HasFlag(PWS_AUTOTRANSPARENT)) {
743 if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) {
744 SetTransparency(PWL_SCROLLBAR_TRANSPARENCY);
745 InvalidateRect();
746 }
747 }
748
749 EndTimer();
750 m_bMouseDown = false;
751
752 return true;
753 }
754
OnNotify(CPWL_Wnd * pWnd,uint32_t msg,intptr_t wParam,intptr_t lParam)755 void CPWL_ScrollBar::OnNotify(CPWL_Wnd* pWnd,
756 uint32_t msg,
757 intptr_t wParam,
758 intptr_t lParam) {
759 CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
760
761 switch (msg) {
762 case PNM_LBUTTONDOWN:
763 if (pWnd == m_pMinButton) {
764 OnMinButtonLBDown(*(CFX_PointF*)lParam);
765 }
766
767 if (pWnd == m_pMaxButton) {
768 OnMaxButtonLBDown(*(CFX_PointF*)lParam);
769 }
770
771 if (pWnd == m_pPosButton) {
772 OnPosButtonLBDown(*(CFX_PointF*)lParam);
773 }
774 break;
775 case PNM_LBUTTONUP:
776 if (pWnd == m_pMinButton) {
777 OnMinButtonLBUp(*(CFX_PointF*)lParam);
778 }
779
780 if (pWnd == m_pMaxButton) {
781 OnMaxButtonLBUp(*(CFX_PointF*)lParam);
782 }
783
784 if (pWnd == m_pPosButton) {
785 OnPosButtonLBUp(*(CFX_PointF*)lParam);
786 }
787 break;
788 case PNM_MOUSEMOVE:
789 if (pWnd == m_pMinButton) {
790 OnMinButtonMouseMove(*(CFX_PointF*)lParam);
791 }
792
793 if (pWnd == m_pMaxButton) {
794 OnMaxButtonMouseMove(*(CFX_PointF*)lParam);
795 }
796
797 if (pWnd == m_pPosButton) {
798 OnPosButtonMouseMove(*(CFX_PointF*)lParam);
799 }
800 break;
801 case PNM_SETSCROLLINFO: {
802 PWL_SCROLL_INFO* pInfo = reinterpret_cast<PWL_SCROLL_INFO*>(lParam);
803 if (pInfo && *pInfo != m_OriginInfo) {
804 m_OriginInfo = *pInfo;
805 FX_FLOAT fMax =
806 pInfo->fContentMax - pInfo->fContentMin - pInfo->fPlateWidth;
807 fMax = fMax > 0.0f ? fMax : 0.0f;
808 SetScrollRange(0, fMax, pInfo->fPlateWidth);
809 SetScrollStep(pInfo->fBigStep, pInfo->fSmallStep);
810 }
811 } break;
812 case PNM_SETSCROLLPOS: {
813 FX_FLOAT fPos = *(FX_FLOAT*)lParam;
814 switch (m_sbType) {
815 case SBT_HSCROLL:
816 fPos = fPos - m_OriginInfo.fContentMin;
817 break;
818 case SBT_VSCROLL:
819 fPos = m_OriginInfo.fContentMax - fPos;
820 break;
821 }
822 SetScrollPos(fPos);
823 } break;
824 }
825 }
826
CreateButtons(const PWL_CREATEPARAM & cp)827 void CPWL_ScrollBar::CreateButtons(const PWL_CREATEPARAM& cp) {
828 PWL_CREATEPARAM scp = cp;
829 scp.pParentWnd = this;
830 scp.dwBorderWidth = 2;
831 scp.nBorderStyle = BorderStyle::BEVELED;
832
833 scp.dwFlags =
834 PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
835
836 if (!m_pMinButton) {
837 m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN);
838 m_pMinButton->Create(scp);
839 }
840
841 if (!m_pMaxButton) {
842 m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX);
843 m_pMaxButton->Create(scp);
844 }
845
846 if (!m_pPosButton) {
847 m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS);
848 m_pPosButton->SetVisible(false);
849 m_pPosButton->Create(scp);
850 }
851 }
852
GetScrollBarWidth() const853 FX_FLOAT CPWL_ScrollBar::GetScrollBarWidth() const {
854 if (!IsVisible())
855 return 0;
856
857 return PWL_SCROLLBAR_WIDTH;
858 }
859
SetScrollRange(FX_FLOAT fMin,FX_FLOAT fMax,FX_FLOAT fClientWidth)860 void CPWL_ScrollBar::SetScrollRange(FX_FLOAT fMin,
861 FX_FLOAT fMax,
862 FX_FLOAT fClientWidth) {
863 if (m_pPosButton) {
864 m_sData.SetScrollRange(fMin, fMax);
865 m_sData.SetClientWidth(fClientWidth);
866
867 if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
868 m_pPosButton->SetVisible(false);
869 } else {
870 m_pPosButton->SetVisible(true);
871 MovePosButton(true);
872 }
873 }
874 }
875
SetScrollPos(FX_FLOAT fPos)876 void CPWL_ScrollBar::SetScrollPos(FX_FLOAT fPos) {
877 FX_FLOAT fOldPos = m_sData.fScrollPos;
878
879 m_sData.SetPos(fPos);
880
881 if (!IsFloatEqual(m_sData.fScrollPos, fOldPos))
882 MovePosButton(true);
883 }
884
SetScrollStep(FX_FLOAT fBigStep,FX_FLOAT fSmallStep)885 void CPWL_ScrollBar::SetScrollStep(FX_FLOAT fBigStep, FX_FLOAT fSmallStep) {
886 m_sData.SetBigStep(fBigStep);
887 m_sData.SetSmallStep(fSmallStep);
888 }
889
MovePosButton(bool bRefresh)890 void CPWL_ScrollBar::MovePosButton(bool bRefresh) {
891 ASSERT(m_pMinButton);
892 ASSERT(m_pMaxButton);
893
894 if (m_pPosButton->IsVisible()) {
895 CFX_FloatRect rcClient;
896 CFX_FloatRect rcPosArea, rcPosButton;
897
898 rcClient = GetClientRect();
899 rcPosArea = GetScrollArea();
900
901 FX_FLOAT fLeft, fRight, fTop, fBottom;
902
903 switch (m_sbType) {
904 case SBT_HSCROLL:
905 fLeft = TrueToFace(m_sData.fScrollPos);
906 fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
907
908 if (fRight - fLeft < PWL_SCROLLBAR_POSBUTTON_MINWIDTH)
909 fRight = fLeft + PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
910
911 if (fRight > rcPosArea.right) {
912 fRight = rcPosArea.right;
913 fLeft = fRight - PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
914 }
915
916 rcPosButton =
917 CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top);
918
919 break;
920 case SBT_VSCROLL:
921 fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
922 fTop = TrueToFace(m_sData.fScrollPos);
923
924 if (IsFloatSmaller(fTop - fBottom, PWL_SCROLLBAR_POSBUTTON_MINWIDTH))
925 fBottom = fTop - PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
926
927 if (IsFloatSmaller(fBottom, rcPosArea.bottom)) {
928 fBottom = rcPosArea.bottom;
929 fTop = fBottom + PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
930 }
931
932 rcPosButton =
933 CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
934
935 break;
936 }
937
938 m_pPosButton->Move(rcPosButton, true, bRefresh);
939 }
940 }
941
OnMinButtonLBDown(const CFX_PointF & point)942 void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) {
943 m_sData.SubSmall();
944 MovePosButton(true);
945 NotifyScrollWindow();
946
947 m_bMinOrMax = true;
948
949 EndTimer();
950 BeginTimer(100);
951 }
952
OnMinButtonLBUp(const CFX_PointF & point)953 void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
954
OnMinButtonMouseMove(const CFX_PointF & point)955 void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {}
956
OnMaxButtonLBDown(const CFX_PointF & point)957 void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) {
958 m_sData.AddSmall();
959 MovePosButton(true);
960 NotifyScrollWindow();
961
962 m_bMinOrMax = false;
963
964 EndTimer();
965 BeginTimer(100);
966 }
967
OnMaxButtonLBUp(const CFX_PointF & point)968 void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
969
OnMaxButtonMouseMove(const CFX_PointF & point)970 void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {}
971
OnPosButtonLBDown(const CFX_PointF & point)972 void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) {
973 m_bMouseDown = true;
974
975 if (m_pPosButton) {
976 CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
977
978 switch (m_sbType) {
979 case SBT_HSCROLL:
980 m_nOldPos = point.x;
981 m_fOldPosButton = rcPosButton.left;
982 break;
983 case SBT_VSCROLL:
984 m_nOldPos = point.y;
985 m_fOldPosButton = rcPosButton.top;
986 break;
987 }
988 }
989 }
990
OnPosButtonLBUp(const CFX_PointF & point)991 void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) {
992 if (m_bMouseDown) {
993 if (!m_bNotifyForever)
994 NotifyScrollWindow();
995 }
996 m_bMouseDown = false;
997 }
998
OnPosButtonMouseMove(const CFX_PointF & point)999 void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) {
1000 FX_FLOAT fOldScrollPos = m_sData.fScrollPos;
1001
1002 FX_FLOAT fNewPos = 0;
1003
1004 switch (m_sbType) {
1005 case SBT_HSCROLL:
1006 if (FXSYS_fabs(point.x - m_nOldPos) < 1)
1007 return;
1008 fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos);
1009 break;
1010 case SBT_VSCROLL:
1011 if (FXSYS_fabs(point.y - m_nOldPos) < 1)
1012 return;
1013 fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos);
1014 break;
1015 }
1016
1017 if (m_bMouseDown) {
1018 switch (m_sbType) {
1019 case SBT_HSCROLL:
1020
1021 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
1022 fNewPos = m_sData.ScrollRange.fMin;
1023 }
1024
1025 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
1026 fNewPos = m_sData.ScrollRange.fMax;
1027 }
1028
1029 m_sData.SetPos(fNewPos);
1030
1031 break;
1032 case SBT_VSCROLL:
1033
1034 if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
1035 fNewPos = m_sData.ScrollRange.fMin;
1036 }
1037
1038 if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
1039 fNewPos = m_sData.ScrollRange.fMax;
1040 }
1041
1042 m_sData.SetPos(fNewPos);
1043
1044 break;
1045 }
1046
1047 if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) {
1048 MovePosButton(true);
1049
1050 if (m_bNotifyForever)
1051 NotifyScrollWindow();
1052 }
1053 }
1054 }
1055
NotifyScrollWindow()1056 void CPWL_ScrollBar::NotifyScrollWindow() {
1057 if (CPWL_Wnd* pParent = GetParentWindow()) {
1058 FX_FLOAT fPos;
1059 switch (m_sbType) {
1060 case SBT_HSCROLL:
1061 fPos = m_OriginInfo.fContentMin + m_sData.fScrollPos;
1062 break;
1063 case SBT_VSCROLL:
1064 fPos = m_OriginInfo.fContentMax - m_sData.fScrollPos;
1065 break;
1066 }
1067 pParent->OnNotify(this, PNM_SCROLLWINDOW, (intptr_t)m_sbType,
1068 (intptr_t)&fPos);
1069 }
1070 }
1071
GetScrollArea() const1072 CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const {
1073 CFX_FloatRect rcClient = GetClientRect();
1074 CFX_FloatRect rcArea;
1075
1076 if (!m_pMinButton || !m_pMaxButton)
1077 return rcClient;
1078
1079 CFX_FloatRect rcMin = m_pMinButton->GetWindowRect();
1080 CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect();
1081
1082 FX_FLOAT fMinWidth = rcMin.right - rcMin.left;
1083 FX_FLOAT fMinHeight = rcMin.top - rcMin.bottom;
1084 FX_FLOAT fMaxWidth = rcMax.right - rcMax.left;
1085 FX_FLOAT fMaxHeight = rcMax.top - rcMax.bottom;
1086
1087 switch (m_sbType) {
1088 case SBT_HSCROLL:
1089 if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) {
1090 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
1091 rcClient.right - fMaxWidth - 1, rcClient.top);
1092 } else {
1093 rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
1094 rcClient.left + fMinWidth + 1, rcClient.top);
1095 }
1096 break;
1097 case SBT_VSCROLL:
1098 if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) {
1099 rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
1100 rcClient.right, rcClient.top - fMaxHeight - 1);
1101 } else {
1102 rcArea =
1103 CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
1104 rcClient.right, rcClient.bottom + fMinHeight + 1);
1105 }
1106 break;
1107 }
1108
1109 rcArea.Normalize();
1110
1111 return rcArea;
1112 }
1113
TrueToFace(FX_FLOAT fTrue)1114 FX_FLOAT CPWL_ScrollBar::TrueToFace(FX_FLOAT fTrue) {
1115 CFX_FloatRect rcPosArea;
1116 rcPosArea = GetScrollArea();
1117
1118 FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
1119 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
1120
1121 FX_FLOAT fFace = 0;
1122
1123 switch (m_sbType) {
1124 case SBT_HSCROLL:
1125 fFace = rcPosArea.left +
1126 fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth;
1127 break;
1128 case SBT_VSCROLL:
1129 fFace = rcPosArea.top -
1130 fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth;
1131 break;
1132 }
1133
1134 return fFace;
1135 }
1136
FaceToTrue(FX_FLOAT fFace)1137 FX_FLOAT CPWL_ScrollBar::FaceToTrue(FX_FLOAT fFace) {
1138 CFX_FloatRect rcPosArea;
1139 rcPosArea = GetScrollArea();
1140
1141 FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
1142 fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
1143
1144 FX_FLOAT fTrue = 0;
1145
1146 switch (m_sbType) {
1147 case SBT_HSCROLL:
1148 fTrue = (fFace - rcPosArea.left) * fFactWidth /
1149 (rcPosArea.right - rcPosArea.left);
1150 break;
1151 case SBT_VSCROLL:
1152 fTrue = (rcPosArea.top - fFace) * fFactWidth /
1153 (rcPosArea.top - rcPosArea.bottom);
1154 break;
1155 }
1156
1157 return fTrue;
1158 }
1159
CreateChildWnd(const PWL_CREATEPARAM & cp)1160 void CPWL_ScrollBar::CreateChildWnd(const PWL_CREATEPARAM& cp) {
1161 CreateButtons(cp);
1162 }
1163
TimerProc()1164 void CPWL_ScrollBar::TimerProc() {
1165 PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
1166 if (m_bMinOrMax)
1167 m_sData.SubSmall();
1168 else
1169 m_sData.AddSmall();
1170
1171 if (sTemp != m_sData) {
1172 MovePosButton(true);
1173 NotifyScrollWindow();
1174 }
1175 }
1176