blob: 016afd6d36606b7d16dd0a505f9a1ca61cef41a7 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
dsinclair447b1f32016-12-08 10:06:32 -08007#include "xfa/fwl/cfwl_scrollbar.h"
Dan Sinclair1770c022016-03-14 14:14:16 -04008
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009#include <algorithm>
10#include <memory>
11#include <utility>
12
dsinclair6fe87952016-11-01 18:48:19 -070013#include "third_party/base/ptr_util.h"
dsinclair447b1f32016-12-08 10:06:32 -080014#include "xfa/fwl/cfwl_messagemouse.h"
15#include "xfa/fwl/cfwl_messagemousewheel.h"
16#include "xfa/fwl/cfwl_notedriver.h"
17#include "xfa/fwl/cfwl_themebackground.h"
18#include "xfa/fwl/cfwl_themepart.h"
19#include "xfa/fwl/cfwl_timerinfo.h"
20#include "xfa/fwl/ifwl_themeprovider.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040021
22#define FWL_SCROLLBAR_Elapse 500
23#define FWL_SCROLLBAR_MinThumb 5
24
dsinclair0ce11ee2016-11-23 16:03:10 -080025CFWL_ScrollBar::CFWL_ScrollBar(
dsinclair1a7534a2016-11-22 15:56:11 -080026 const CFWL_App* app,
dsinclaira5811f02016-11-03 12:27:25 -070027 std::unique_ptr<CFWL_WidgetProperties> properties,
dsinclair2c489cc2016-11-23 16:17:20 -080028 CFWL_Widget* pOuter)
29 : CFWL_Widget(app, std::move(properties), pOuter),
tsepez6f4f2332016-06-06 13:23:55 -070030 m_pTimerInfo(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040031 m_fRangeMin(0),
32 m_fRangeMax(-1),
33 m_fPageSize(0),
34 m_fStepSize(0),
35 m_fPos(0),
36 m_fTrackPos(0),
dsinclairf87058d2016-04-21 06:22:11 -070037 m_iMinButtonState(CFWL_PartState_Normal),
38 m_iMaxButtonState(CFWL_PartState_Normal),
39 m_iThumbButtonState(CFWL_PartState_Normal),
40 m_iMinTrackState(CFWL_PartState_Normal),
41 m_iMaxTrackState(CFWL_PartState_Normal),
Dan Sinclair1770c022016-03-14 14:14:16 -040042 m_fLastTrackPos(0),
43 m_cpTrackPointX(0),
44 m_cpTrackPointY(0),
45 m_iMouseWheel(0),
tsepezd19e9122016-11-02 15:43:18 -070046 m_bMouseDown(false),
Dan Sinclair1770c022016-03-14 14:14:16 -040047 m_fButtonLen(0),
tsepezd19e9122016-11-02 15:43:18 -070048 m_bMinSize(false),
dsinclair20855382016-10-31 07:29:34 -070049 m_fMinThumb(FWL_SCROLLBAR_MinThumb),
50 m_Timer(this) {
Dan Sinclair1770c022016-03-14 14:14:16 -040051 m_rtClient.Reset();
52 m_rtThumb.Reset();
53 m_rtMinBtn.Reset();
54 m_rtMaxBtn.Reset();
55 m_rtMinTrack.Reset();
56 m_rtMaxTrack.Reset();
57}
dsinclairb4d40ff2016-05-05 10:28:02 -070058
dsinclair0ce11ee2016-11-23 16:03:10 -080059CFWL_ScrollBar::~CFWL_ScrollBar() {}
dsinclairb4d40ff2016-05-05 10:28:02 -070060
dsinclair0ce11ee2016-11-23 16:03:10 -080061FWL_Type CFWL_ScrollBar::GetClassID() const {
dsinclair20855382016-10-31 07:29:34 -070062 return FWL_Type::ScrollBar;
63}
64
dsinclair0ce11ee2016-11-23 16:03:10 -080065void CFWL_ScrollBar::Update() {
dsinclair058d2d62016-11-16 13:54:01 -080066 if (IsLocked())
dsinclair98329fe2016-11-10 09:40:14 -080067 return;
dsinclair058d2d62016-11-16 13:54:01 -080068 if (!m_pProperties->m_pThemeProvider)
Dan Sinclair1770c022016-03-14 14:14:16 -040069 m_pProperties->m_pThemeProvider = GetAvailableTheme();
dsinclair058d2d62016-11-16 13:54:01 -080070
Dan Sinclair1770c022016-03-14 14:14:16 -040071 Layout();
Dan Sinclair1770c022016-03-14 14:14:16 -040072}
dsinclairfb505592016-10-20 06:44:03 -070073
dsinclair0ce11ee2016-11-23 16:03:10 -080074void CFWL_ScrollBar::DrawWidget(CFX_Graphics* pGraphics,
dsinclair98329fe2016-11-10 09:40:14 -080075 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -040076 if (!pGraphics)
dsinclair98329fe2016-11-10 09:40:14 -080077 return;
Dan Sinclair1770c022016-03-14 14:14:16 -040078 if (!m_pProperties->m_pThemeProvider)
dsinclair98329fe2016-11-10 09:40:14 -080079 return;
dsinclair058d2d62016-11-16 13:54:01 -080080
Dan Sinclair1770c022016-03-14 14:14:16 -040081 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
dsinclair058d2d62016-11-16 13:54:01 -080082 if (HasBorder())
dsinclairf87058d2016-04-21 06:22:11 -070083 DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
tsepezd19e9122016-11-02 15:43:18 -070084 DrawTrack(pGraphics, pTheme, true, pMatrix);
85 DrawTrack(pGraphics, pTheme, false, pMatrix);
86 DrawArrowBtn(pGraphics, pTheme, true, pMatrix);
87 DrawArrowBtn(pGraphics, pTheme, false, pMatrix);
Dan Sinclair1770c022016-03-14 14:14:16 -040088 DrawThumb(pGraphics, pTheme, pMatrix);
Dan Sinclair1770c022016-03-14 14:14:16 -040089}
dsinclairfb505592016-10-20 06:44:03 -070090
dsinclair0ce11ee2016-11-23 16:03:10 -080091void CFWL_ScrollBar::SetTrackPos(FX_FLOAT fTrackPos) {
Dan Sinclair1770c022016-03-14 14:14:16 -040092 m_fTrackPos = fTrackPos;
Dan Sinclairdb194cf2017-01-02 15:45:12 -050093 m_rtThumb = CalcThumbButtonRect(m_rtThumb);
94 m_rtMinTrack = CalcMinTrackRect(m_rtMinTrack);
95 m_rtMaxTrack = CalcMaxTrackRect(m_rtMaxTrack);
Dan Sinclair1770c022016-03-14 14:14:16 -040096}
dsinclairfb505592016-10-20 06:44:03 -070097
dsinclair447b1f32016-12-08 10:06:32 -080098bool CFWL_ScrollBar::DoScroll(CFWL_EventScroll::Code dwCode, FX_FLOAT fPos) {
99 if (dwCode == CFWL_EventScroll::Code::None)
dsinclair3e577c22016-11-10 11:01:16 -0800100 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400101 return OnScroll(dwCode, fPos);
102}
tsepez6f4f2332016-06-06 13:23:55 -0700103
dsinclair0ce11ee2016-11-23 16:03:10 -0800104void CFWL_ScrollBar::DrawTrack(CFX_Graphics* pGraphics,
dsinclairfb505592016-10-20 06:44:03 -0700105 IFWL_ThemeProvider* pTheme,
tsepezd19e9122016-11-02 15:43:18 -0700106 bool bLower,
dsinclairfb505592016-10-20 06:44:03 -0700107 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400108 CFWL_ThemeBackground param;
dsinclairfb505592016-10-20 06:44:03 -0700109 param.m_pWidget = this;
dsinclairf87058d2016-04-21 06:22:11 -0700110 param.m_iPart = bLower ? CFWL_Part::LowerTrack : CFWL_Part::UpperTrack;
Dan Sinclair1770c022016-03-14 14:14:16 -0400111 param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
dsinclairf87058d2016-04-21 06:22:11 -0700112 ? CFWL_PartState_Disabled
Dan Sinclair1770c022016-03-14 14:14:16 -0400113 : (bLower ? m_iMinTrackState : m_iMaxTrackState);
114 param.m_pGraphics = pGraphics;
115 param.m_matrix.Concat(*pMatrix);
116 param.m_rtPart = bLower ? m_rtMinTrack : m_rtMaxTrack;
117 pTheme->DrawBackground(&param);
118}
dsinclairfb505592016-10-20 06:44:03 -0700119
dsinclair0ce11ee2016-11-23 16:03:10 -0800120void CFWL_ScrollBar::DrawArrowBtn(CFX_Graphics* pGraphics,
dsinclairfb505592016-10-20 06:44:03 -0700121 IFWL_ThemeProvider* pTheme,
tsepezd19e9122016-11-02 15:43:18 -0700122 bool bMinBtn,
dsinclairfb505592016-10-20 06:44:03 -0700123 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400124 CFWL_ThemeBackground param;
dsinclairfb505592016-10-20 06:44:03 -0700125 param.m_pWidget = this;
dsinclairf87058d2016-04-21 06:22:11 -0700126 param.m_iPart = bMinBtn ? CFWL_Part::ForeArrow : CFWL_Part::BackArrow;
Dan Sinclair1770c022016-03-14 14:14:16 -0400127 param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
dsinclairf87058d2016-04-21 06:22:11 -0700128 ? CFWL_PartState_Disabled
Dan Sinclair1770c022016-03-14 14:14:16 -0400129 : (bMinBtn ? m_iMinButtonState : m_iMaxButtonState);
130 param.m_pGraphics = pGraphics;
131 param.m_matrix.Concat(*pMatrix);
132 param.m_rtPart = bMinBtn ? m_rtMinBtn : m_rtMaxBtn;
dsinclair058d2d62016-11-16 13:54:01 -0800133 if (param.m_rtPart.height > 0 && param.m_rtPart.width > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400134 pTheme->DrawBackground(&param);
Dan Sinclair1770c022016-03-14 14:14:16 -0400135}
dsinclairfb505592016-10-20 06:44:03 -0700136
dsinclair0ce11ee2016-11-23 16:03:10 -0800137void CFWL_ScrollBar::DrawThumb(CFX_Graphics* pGraphics,
dsinclairfb505592016-10-20 06:44:03 -0700138 IFWL_ThemeProvider* pTheme,
139 const CFX_Matrix* pMatrix) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400140 CFWL_ThemeBackground param;
dsinclairfb505592016-10-20 06:44:03 -0700141 param.m_pWidget = this;
dsinclairf87058d2016-04-21 06:22:11 -0700142 param.m_iPart = CFWL_Part::Thumb;
Dan Sinclair1770c022016-03-14 14:14:16 -0400143 param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
dsinclairf87058d2016-04-21 06:22:11 -0700144 ? CFWL_PartState_Disabled
Dan Sinclair1770c022016-03-14 14:14:16 -0400145 : m_iThumbButtonState;
146 param.m_pGraphics = pGraphics;
147 param.m_matrix.Concat(*pMatrix);
148 param.m_rtPart = m_rtThumb;
149 pTheme->DrawBackground(&param);
150}
dsinclairfb505592016-10-20 06:44:03 -0700151
dsinclair0ce11ee2016-11-23 16:03:10 -0800152void CFWL_ScrollBar::Layout() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400153 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
154 CFWL_ThemePart part;
dsinclairfb505592016-10-20 06:44:03 -0700155 part.m_pWidget = this;
Dan Sinclair1770c022016-03-14 14:14:16 -0400156 m_fMinThumb = *static_cast<FX_FLOAT*>(
dsinclairf87058d2016-04-21 06:22:11 -0700157 pTheme->GetCapacity(&part, CFWL_WidgetCapacity::Size));
dsinclair43ac44c2016-12-08 14:05:14 -0800158 m_rtClient = GetClientRect();
Dan Sinclair1770c022016-03-14 14:14:16 -0400159 CalcButtonLen();
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500160 m_rtMinBtn = CalcMinButtonRect();
161 m_rtMaxBtn = CalcMaxButtonRect();
162 m_rtThumb = CalcThumbButtonRect(m_rtThumb);
163 m_rtMinTrack = CalcMinTrackRect(m_rtMinTrack);
164 m_rtMaxTrack = CalcMaxTrackRect(m_rtMaxTrack);
Dan Sinclair1770c022016-03-14 14:14:16 -0400165}
dsinclairfb505592016-10-20 06:44:03 -0700166
dsinclair0ce11ee2016-11-23 16:03:10 -0800167void CFWL_ScrollBar::CalcButtonLen() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400168 m_fButtonLen = IsVertical() ? m_rtClient.width : m_rtClient.height;
169 FX_FLOAT fLength = IsVertical() ? m_rtClient.height : m_rtClient.width;
170 if (fLength < m_fButtonLen * 2) {
171 m_fButtonLen = fLength / 2;
tsepezd19e9122016-11-02 15:43:18 -0700172 m_bMinSize = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400173 } else {
tsepezd19e9122016-11-02 15:43:18 -0700174 m_bMinSize = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400175 }
176}
dsinclairfb505592016-10-20 06:44:03 -0700177
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500178CFX_RectF CFWL_ScrollBar::CalcMinButtonRect() {
179 CFX_RectF rect;
180 if (IsVertical())
181 rect.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width, m_fButtonLen);
182 else
183 rect.Set(m_rtClient.left, m_rtClient.top, m_fButtonLen, m_rtClient.height);
184 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400185}
dsinclair878dd5b2016-10-17 18:14:25 -0700186
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500187CFX_RectF CFWL_ScrollBar::CalcMaxButtonRect() {
188 CFX_RectF rect;
189 if (IsVertical()) {
190 rect.Set(m_rtClient.left, m_rtClient.bottom() - m_fButtonLen,
191 m_rtClient.width, m_fButtonLen);
192 } else {
193 rect.Set(m_rtClient.right() - m_fButtonLen, m_rtClient.top, m_fButtonLen,
194 m_rtClient.height);
Dan Sinclair1770c022016-03-14 14:14:16 -0400195 }
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500196 return rect;
197}
198
199CFX_RectF CFWL_ScrollBar::CalcThumbButtonRect(const CFX_RectF& rtThumb) {
200 CFX_RectF rect;
201 rect.Reset();
202
203 if (!IsEnabled())
204 return rect;
205
Dan Sinclair1770c022016-03-14 14:14:16 -0400206 if (m_bMinSize) {
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500207 rect.left = rtThumb.left;
208 rect.top = rtThumb.top;
209 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400210 }
dsinclair058d2d62016-11-16 13:54:01 -0800211
Dan Sinclair1770c022016-03-14 14:14:16 -0400212 FX_FLOAT fRange = m_fRangeMax - m_fRangeMin;
Dan Sinclair1770c022016-03-14 14:14:16 -0400213 if (fRange < 0) {
dsinclair058d2d62016-11-16 13:54:01 -0800214 if (IsVertical())
Dan Sinclair1770c022016-03-14 14:14:16 -0400215 rect.Set(m_rtClient.left, m_rtMaxBtn.bottom(), m_rtClient.width, 0);
dsinclair058d2d62016-11-16 13:54:01 -0800216 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400217 rect.Set(m_rtMaxBtn.right(), m_rtClient.top, 0, m_rtClient.height);
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500218 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400219 }
dsinclair058d2d62016-11-16 13:54:01 -0800220
Dan Sinclair1770c022016-03-14 14:14:16 -0400221 CFX_RectF rtClient = m_rtClient;
222 FX_FLOAT fLength = IsVertical() ? rtClient.height : rtClient.width;
223 FX_FLOAT fSize = m_fButtonLen;
dsinclair30e5f302016-11-21 12:18:28 -0800224 fLength -= fSize * 2.0f;
225 if (fLength < fSize)
226 fLength = 0.0f;
dsinclair058d2d62016-11-16 13:54:01 -0800227
Dan Sinclair1770c022016-03-14 14:14:16 -0400228 FX_FLOAT fThumbSize = fLength * fLength / (fRange + fLength);
dsinclair058d2d62016-11-16 13:54:01 -0800229 fThumbSize = std::max(fThumbSize, m_fMinThumb);
230
231 FX_FLOAT fDiff = std::max(fLength - fThumbSize, 0.0f);
232 FX_FLOAT fTrackPos =
233 std::max(std::min(m_fTrackPos, m_fRangeMax), m_fRangeMin);
Dan Sinclair1770c022016-03-14 14:14:16 -0400234 if (!fRange)
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500235 return rect;
dsinclair058d2d62016-11-16 13:54:01 -0800236
dsinclair30e5f302016-11-21 12:18:28 -0800237 FX_FLOAT iPos = fSize + fDiff * (fTrackPos - m_fRangeMin) / fRange;
238 rect.left = rtClient.left;
dsinclair30e5f302016-11-21 12:18:28 -0800239 rect.top = rtClient.top;
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500240 if (IsVertical()) {
dsinclair30e5f302016-11-21 12:18:28 -0800241 rect.top += iPos;
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500242 rect.width = rtClient.width;
243 rect.height = fThumbSize;
244 } else {
245 rect.left += iPos;
246 rect.width = fThumbSize;
247 rect.height = rtClient.height;
248 }
249 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400250}
dsinclairfb505592016-10-20 06:44:03 -0700251
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500252CFX_RectF CFWL_ScrollBar::CalcMinTrackRect(const CFX_RectF& rtMinRect) {
253 CFX_RectF rect;
254 rect.Reset();
255
Dan Sinclair1770c022016-03-14 14:14:16 -0400256 if (m_bMinSize) {
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500257 rect.left = rtMinRect.left;
258 rect.top = rtMinRect.top;
259 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400260 }
dsinclair058d2d62016-11-16 13:54:01 -0800261
Dan Sinclair1770c022016-03-14 14:14:16 -0400262 rect.left = m_rtClient.left;
263 rect.top = m_rtClient.top;
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500264 if (IsVertical()) {
265 rect.width = m_rtClient.width;
266 rect.height = (m_rtThumb.top + m_rtThumb.bottom()) / 2;
267 } else {
268 rect.width = (m_rtThumb.left + m_rtThumb.right()) / 2;
269 rect.height = m_rtClient.height;
270 }
271 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400272}
dsinclairfb505592016-10-20 06:44:03 -0700273
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500274CFX_RectF CFWL_ScrollBar::CalcMaxTrackRect(const CFX_RectF& rtMaxRect) {
275 CFX_RectF rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400276 if (m_bMinSize) {
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500277 rect.Set(rtMaxRect.left, rtMaxRect.top, 0, 0);
278 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400279 }
dsinclair058d2d62016-11-16 13:54:01 -0800280
Dan Sinclairdb194cf2017-01-02 15:45:12 -0500281 if (IsVertical()) {
282 FX_FLOAT iy = (m_rtThumb.top + m_rtThumb.bottom()) / 2;
283 rect.Set(m_rtClient.left, iy, m_rtClient.width, m_rtClient.bottom() - iy);
284 } else {
285 FX_FLOAT ix = (m_rtThumb.left + m_rtThumb.right()) / 2;
286 rect.Set(ix, m_rtClient.top, m_rtClient.height - ix, m_rtClient.height);
287 }
288 return rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400289}
dsinclairfb505592016-10-20 06:44:03 -0700290
dsinclair0ce11ee2016-11-23 16:03:10 -0800291FX_FLOAT CFWL_ScrollBar::GetTrackPointPos(FX_FLOAT fx, FX_FLOAT fy) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400292 FX_FLOAT fDiffX = fx - m_cpTrackPointX;
293 FX_FLOAT fDiffY = fy - m_cpTrackPointY;
294 FX_FLOAT fRange = m_fRangeMax - m_fRangeMin;
295 FX_FLOAT fPos;
dsinclair30e5f302016-11-21 12:18:28 -0800296
297 if (IsVertical()) {
298 fPos = fRange * fDiffY /
299 (m_rtMaxBtn.top - m_rtMinBtn.bottom() - m_rtThumb.height);
Dan Sinclair1770c022016-03-14 14:14:16 -0400300 } else {
dsinclair30e5f302016-11-21 12:18:28 -0800301 fPos = fRange * fDiffX /
302 (m_rtMaxBtn.left - m_rtMinBtn.right() - m_rtThumb.width);
Dan Sinclair1770c022016-03-14 14:14:16 -0400303 }
dsinclair30e5f302016-11-21 12:18:28 -0800304
Dan Sinclair1770c022016-03-14 14:14:16 -0400305 fPos += m_fLastTrackPos;
dsinclair058d2d62016-11-16 13:54:01 -0800306 return std::min(std::max(fPos, m_fRangeMin), m_fRangeMax);
Dan Sinclair1770c022016-03-14 14:14:16 -0400307}
dsinclairfb505592016-10-20 06:44:03 -0700308
dsinclair0ce11ee2016-11-23 16:03:10 -0800309bool CFWL_ScrollBar::SendEvent() {
dsinclairf87058d2016-04-21 06:22:11 -0700310 if (m_iMinButtonState == CFWL_PartState_Pressed) {
dsinclair447b1f32016-12-08 10:06:32 -0800311 DoScroll(CFWL_EventScroll::Code::StepBackward, m_fTrackPos);
tsepezd19e9122016-11-02 15:43:18 -0700312 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400313 }
dsinclairf87058d2016-04-21 06:22:11 -0700314 if (m_iMaxButtonState == CFWL_PartState_Pressed) {
dsinclair447b1f32016-12-08 10:06:32 -0800315 DoScroll(CFWL_EventScroll::Code::StepForward, m_fTrackPos);
tsepezd19e9122016-11-02 15:43:18 -0700316 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400317 }
dsinclairf87058d2016-04-21 06:22:11 -0700318 if (m_iMinTrackState == CFWL_PartState_Pressed) {
dsinclair447b1f32016-12-08 10:06:32 -0800319 DoScroll(CFWL_EventScroll::Code::PageBackward, m_fTrackPos);
Dan Sinclair1770c022016-03-14 14:14:16 -0400320 return m_rtThumb.Contains(m_cpTrackPointX, m_cpTrackPointY);
321 }
dsinclairf87058d2016-04-21 06:22:11 -0700322 if (m_iMaxTrackState == CFWL_PartState_Pressed) {
dsinclair447b1f32016-12-08 10:06:32 -0800323 DoScroll(CFWL_EventScroll::Code::PageForward, m_fTrackPos);
Dan Sinclair1770c022016-03-14 14:14:16 -0400324 return m_rtThumb.Contains(m_cpTrackPointX, m_cpTrackPointY);
325 }
326 if (m_iMouseWheel) {
dsinclair447b1f32016-12-08 10:06:32 -0800327 CFWL_EventScroll::Code dwCode = m_iMouseWheel < 0
328 ? CFWL_EventScroll::Code::StepForward
329 : CFWL_EventScroll::Code::StepBackward;
Dan Sinclair1770c022016-03-14 14:14:16 -0400330 DoScroll(dwCode, m_fTrackPos);
331 }
tsepezd19e9122016-11-02 15:43:18 -0700332 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400333}
dsinclairfb505592016-10-20 06:44:03 -0700334
dsinclair447b1f32016-12-08 10:06:32 -0800335bool CFWL_ScrollBar::OnScroll(CFWL_EventScroll::Code dwCode, FX_FLOAT fPos) {
336 CFWL_EventScroll ev(this);
Dan Sinclair1770c022016-03-14 14:14:16 -0400337 ev.m_iScrollCode = dwCode;
Dan Sinclair1770c022016-03-14 14:14:16 -0400338 ev.m_fPos = fPos;
Dan Sinclair1770c022016-03-14 14:14:16 -0400339 DispatchEvent(&ev);
dsinclair4614b452016-12-07 17:01:58 -0800340 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400341}
dsinclair5d9da0c2016-04-21 13:12:06 -0700342
dsinclair0ce11ee2016-11-23 16:03:10 -0800343void CFWL_ScrollBar::OnProcessMessage(CFWL_Message* pMessage) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400344 if (!pMessage)
dsinclairc777f482016-05-04 17:57:03 -0700345 return;
dsinclair5d9da0c2016-04-21 13:12:06 -0700346
dsinclair4614b452016-12-07 17:01:58 -0800347 CFWL_Message::Type type = pMessage->GetType();
348 if (type == CFWL_Message::Type::Mouse) {
dsinclair447b1f32016-12-08 10:06:32 -0800349 CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
dsinclair8f4bf9a2016-05-04 13:51:51 -0700350 switch (pMsg->m_dwCmd) {
dsinclair3b3ce1a2016-11-02 14:51:25 -0700351 case FWL_MouseCommand::LeftButtonDown:
Dan Sinclair1770c022016-03-14 14:14:16 -0400352 OnLButtonDown(pMsg->m_dwFlags, pMsg->m_fx, pMsg->m_fy);
353 break;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700354 case FWL_MouseCommand::LeftButtonUp:
Dan Sinclair1770c022016-03-14 14:14:16 -0400355 OnLButtonUp(pMsg->m_dwFlags, pMsg->m_fx, pMsg->m_fy);
356 break;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700357 case FWL_MouseCommand::Move:
Dan Sinclair1770c022016-03-14 14:14:16 -0400358 OnMouseMove(pMsg->m_dwFlags, pMsg->m_fx, pMsg->m_fy);
359 break;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700360 case FWL_MouseCommand::Leave:
Dan Sinclair1770c022016-03-14 14:14:16 -0400361 OnMouseLeave();
362 break;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700363 default:
364 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 }
dsinclair4614b452016-12-07 17:01:58 -0800366 } else if (type == CFWL_Message::Type::MouseWheel) {
dsinclair447b1f32016-12-08 10:06:32 -0800367 CFWL_MessageMouseWheel* pMsg =
368 static_cast<CFWL_MessageMouseWheel*>(pMessage);
Dan Sinclair1770c022016-03-14 14:14:16 -0400369 OnMouseWheel(pMsg->m_fx, pMsg->m_fy, pMsg->m_dwFlags, pMsg->m_fDeltaX,
370 pMsg->m_fDeltaY);
Dan Sinclair1770c022016-03-14 14:14:16 -0400371 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400372}
dsinclair5d9da0c2016-04-21 13:12:06 -0700373
dsinclair0ce11ee2016-11-23 16:03:10 -0800374void CFWL_ScrollBar::OnDrawWidget(CFX_Graphics* pGraphics,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700375 const CFX_Matrix* pMatrix) {
376 DrawWidget(pGraphics, pMatrix);
Dan Sinclair1770c022016-03-14 14:14:16 -0400377}
dsinclairc777f482016-05-04 17:57:03 -0700378
dsinclair0ce11ee2016-11-23 16:03:10 -0800379void CFWL_ScrollBar::OnLButtonDown(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
dsinclair3b3ce1a2016-11-02 14:51:25 -0700380 if (!IsEnabled())
Dan Sinclair1770c022016-03-14 14:14:16 -0400381 return;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700382
tsepezd19e9122016-11-02 15:43:18 -0700383 m_bMouseDown = true;
384 SetGrab(true);
dsinclair3b3ce1a2016-11-02 14:51:25 -0700385 m_cpTrackPointX = fx;
386 m_cpTrackPointY = fy;
387 m_fLastTrackPos = m_fTrackPos;
388 if (m_rtMinBtn.Contains(fx, fy))
389 DoMouseDown(0, m_rtMinBtn, m_iMinButtonState, fx, fy);
390 else if (m_rtThumb.Contains(fx, fy))
391 DoMouseDown(1, m_rtThumb, m_iThumbButtonState, fx, fy);
392 else if (m_rtMaxBtn.Contains(fx, fy))
393 DoMouseDown(2, m_rtMaxBtn, m_iMaxButtonState, fx, fy);
394 else if (m_rtMinTrack.Contains(fx, fy))
395 DoMouseDown(3, m_rtMinTrack, m_iMinTrackState, fx, fy);
396 else
397 DoMouseDown(4, m_rtMaxTrack, m_iMaxTrackState, fx, fy);
398
399 if (!SendEvent())
400 m_pTimerInfo = m_Timer.StartTimer(FWL_SCROLLBAR_Elapse, true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400401}
tsepez6f4f2332016-06-06 13:23:55 -0700402
dsinclair0ce11ee2016-11-23 16:03:10 -0800403void CFWL_ScrollBar::OnLButtonUp(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
dsinclair3b3ce1a2016-11-02 14:51:25 -0700404 m_pTimerInfo->StopTimer();
tsepezd19e9122016-11-02 15:43:18 -0700405 m_bMouseDown = false;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700406 DoMouseUp(0, m_rtMinBtn, m_iMinButtonState, fx, fy);
407 DoMouseUp(1, m_rtThumb, m_iThumbButtonState, fx, fy);
408 DoMouseUp(2, m_rtMaxBtn, m_iMaxButtonState, fx, fy);
409 DoMouseUp(3, m_rtMinTrack, m_iMinTrackState, fx, fy);
410 DoMouseUp(4, m_rtMaxTrack, m_iMaxTrackState, fx, fy);
tsepezd19e9122016-11-02 15:43:18 -0700411 SetGrab(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400412}
dsinclairfb505592016-10-20 06:44:03 -0700413
dsinclair0ce11ee2016-11-23 16:03:10 -0800414void CFWL_ScrollBar::OnMouseMove(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
dsinclair3b3ce1a2016-11-02 14:51:25 -0700415 DoMouseMove(0, m_rtMinBtn, m_iMinButtonState, fx, fy);
416 DoMouseMove(1, m_rtThumb, m_iThumbButtonState, fx, fy);
417 DoMouseMove(2, m_rtMaxBtn, m_iMaxButtonState, fx, fy);
418 DoMouseMove(3, m_rtMinTrack, m_iMinTrackState, fx, fy);
419 DoMouseMove(4, m_rtMaxTrack, m_iMaxTrackState, fx, fy);
Dan Sinclair1770c022016-03-14 14:14:16 -0400420}
dsinclairfb505592016-10-20 06:44:03 -0700421
dsinclair0ce11ee2016-11-23 16:03:10 -0800422void CFWL_ScrollBar::OnMouseLeave() {
dsinclair3b3ce1a2016-11-02 14:51:25 -0700423 DoMouseLeave(0, m_rtMinBtn, m_iMinButtonState);
424 DoMouseLeave(1, m_rtThumb, m_iThumbButtonState);
425 DoMouseLeave(2, m_rtMaxBtn, m_iMaxButtonState);
426 DoMouseLeave(3, m_rtMinTrack, m_iMinTrackState);
427 DoMouseLeave(4, m_rtMaxTrack, m_iMaxTrackState);
Dan Sinclair1770c022016-03-14 14:14:16 -0400428}
dsinclairfb505592016-10-20 06:44:03 -0700429
dsinclair0ce11ee2016-11-23 16:03:10 -0800430void CFWL_ScrollBar::OnMouseWheel(FX_FLOAT fx,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700431 FX_FLOAT fy,
432 uint32_t dwFlags,
433 FX_FLOAT fDeltaX,
434 FX_FLOAT fDeltaY) {
435 m_iMouseWheel = (int32_t)fDeltaX;
436 SendEvent();
437 m_iMouseWheel = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400438}
dsinclairfb505592016-10-20 06:44:03 -0700439
dsinclair0ce11ee2016-11-23 16:03:10 -0800440void CFWL_ScrollBar::DoMouseDown(int32_t iItem,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700441 const CFX_RectF& rtItem,
442 int32_t& iState,
443 FX_FLOAT fx,
444 FX_FLOAT fy) {
445 if (!rtItem.Contains(fx, fy))
Dan Sinclair1770c022016-03-14 14:14:16 -0400446 return;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700447 if (iState == CFWL_PartState_Pressed)
Dan Sinclair1770c022016-03-14 14:14:16 -0400448 return;
dsinclair058d2d62016-11-16 13:54:01 -0800449
dsinclairf87058d2016-04-21 06:22:11 -0700450 iState = CFWL_PartState_Pressed;
dsinclair43ac44c2016-12-08 14:05:14 -0800451 RepaintRect(rtItem);
Dan Sinclair1770c022016-03-14 14:14:16 -0400452}
dsinclairfb505592016-10-20 06:44:03 -0700453
dsinclair0ce11ee2016-11-23 16:03:10 -0800454void CFWL_ScrollBar::DoMouseUp(int32_t iItem,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700455 const CFX_RectF& rtItem,
456 int32_t& iState,
457 FX_FLOAT fx,
458 FX_FLOAT fy) {
dsinclairf87058d2016-04-21 06:22:11 -0700459 int32_t iNewState =
460 rtItem.Contains(fx, fy) ? CFWL_PartState_Hovered : CFWL_PartState_Normal;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700461 if (iState == iNewState)
Dan Sinclair1770c022016-03-14 14:14:16 -0400462 return;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700463
Dan Sinclair1770c022016-03-14 14:14:16 -0400464 iState = iNewState;
dsinclair43ac44c2016-12-08 14:05:14 -0800465 RepaintRect(rtItem);
dsinclair447b1f32016-12-08 10:06:32 -0800466 OnScroll(CFWL_EventScroll::Code::EndScroll, m_fTrackPos);
Dan Sinclair1770c022016-03-14 14:14:16 -0400467}
dsinclairfb505592016-10-20 06:44:03 -0700468
dsinclair0ce11ee2016-11-23 16:03:10 -0800469void CFWL_ScrollBar::DoMouseMove(int32_t iItem,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700470 const CFX_RectF& rtItem,
471 int32_t& iState,
472 FX_FLOAT fx,
473 FX_FLOAT fy) {
474 if (!m_bMouseDown) {
dsinclairf87058d2016-04-21 06:22:11 -0700475 int32_t iNewState = rtItem.Contains(fx, fy) ? CFWL_PartState_Hovered
476 : CFWL_PartState_Normal;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700477 if (iState == iNewState)
Dan Sinclair1770c022016-03-14 14:14:16 -0400478 return;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700479
Dan Sinclair1770c022016-03-14 14:14:16 -0400480 iState = iNewState;
dsinclair43ac44c2016-12-08 14:05:14 -0800481 RepaintRect(rtItem);
dsinclair3b3ce1a2016-11-02 14:51:25 -0700482 } else if ((2 == iItem) && (m_iThumbButtonState == CFWL_PartState_Pressed)) {
483 FX_FLOAT fPos = GetTrackPointPos(fx, fy);
484 m_fTrackPos = fPos;
dsinclair447b1f32016-12-08 10:06:32 -0800485 OnScroll(CFWL_EventScroll::Code::TrackPos, fPos);
Dan Sinclair1770c022016-03-14 14:14:16 -0400486 }
487}
dsinclairfb505592016-10-20 06:44:03 -0700488
dsinclair0ce11ee2016-11-23 16:03:10 -0800489void CFWL_ScrollBar::DoMouseLeave(int32_t iItem,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700490 const CFX_RectF& rtItem,
491 int32_t& iState) {
492 if (iState == CFWL_PartState_Normal)
Dan Sinclair1770c022016-03-14 14:14:16 -0400493 return;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700494
dsinclairf87058d2016-04-21 06:22:11 -0700495 iState = CFWL_PartState_Normal;
dsinclair43ac44c2016-12-08 14:05:14 -0800496 RepaintRect(rtItem);
Dan Sinclair1770c022016-03-14 14:14:16 -0400497}
dsinclairfb505592016-10-20 06:44:03 -0700498
dsinclair0ce11ee2016-11-23 16:03:10 -0800499void CFWL_ScrollBar::DoMouseHover(int32_t iItem,
dsinclair3b3ce1a2016-11-02 14:51:25 -0700500 const CFX_RectF& rtItem,
501 int32_t& iState) {
502 if (iState == CFWL_PartState_Hovered)
Dan Sinclair1770c022016-03-14 14:14:16 -0400503 return;
dsinclair3b3ce1a2016-11-02 14:51:25 -0700504
dsinclairf87058d2016-04-21 06:22:11 -0700505 iState = CFWL_PartState_Hovered;
dsinclair43ac44c2016-12-08 14:05:14 -0800506 RepaintRect(rtItem);
Dan Sinclair1770c022016-03-14 14:14:16 -0400507}
dsinclair20855382016-10-31 07:29:34 -0700508
dsinclair0ce11ee2016-11-23 16:03:10 -0800509CFWL_ScrollBar::Timer::Timer(CFWL_ScrollBar* pToolTip) : CFWL_Timer(pToolTip) {}
dsinclair20855382016-10-31 07:29:34 -0700510
dsinclair0ce11ee2016-11-23 16:03:10 -0800511void CFWL_ScrollBar::Timer::Run(CFWL_TimerInfo* pTimerInfo) {
512 CFWL_ScrollBar* pButton = static_cast<CFWL_ScrollBar*>(m_pWidget);
dsinclair20855382016-10-31 07:29:34 -0700513
514 if (pButton->m_pTimerInfo)
515 pButton->m_pTimerInfo->StopTimer();
516
517 if (!pButton->SendEvent())
518 pButton->m_pTimerInfo = StartTimer(0, true);
519}