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