1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_pushbutton.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fde/cfde_textout.h"
10*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_event.h"
11*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_eventmouse.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_messagekey.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_messagemouse.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_notedriver.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_themebackground.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/cfwl_themetext.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/fwl_widgetdef.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fwl/ifwl_themeprovider.h"
19*3ac0a46fSAndroid Build Coastguard Worker
CFWL_PushButton(CFWL_App * app)20*3ac0a46fSAndroid Build Coastguard Worker CFWL_PushButton::CFWL_PushButton(CFWL_App* app)
21*3ac0a46fSAndroid Build Coastguard Worker : CFWL_Widget(app, Properties(), nullptr) {}
22*3ac0a46fSAndroid Build Coastguard Worker
23*3ac0a46fSAndroid Build Coastguard Worker CFWL_PushButton::~CFWL_PushButton() = default;
24*3ac0a46fSAndroid Build Coastguard Worker
GetClassID() const25*3ac0a46fSAndroid Build Coastguard Worker FWL_Type CFWL_PushButton::GetClassID() const {
26*3ac0a46fSAndroid Build Coastguard Worker return FWL_Type::PushButton;
27*3ac0a46fSAndroid Build Coastguard Worker }
28*3ac0a46fSAndroid Build Coastguard Worker
SetStates(uint32_t dwStates)29*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::SetStates(uint32_t dwStates) {
30*3ac0a46fSAndroid Build Coastguard Worker if (dwStates & FWL_STATE_WGT_Disabled) {
31*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates = FWL_STATE_WGT_Disabled;
32*3ac0a46fSAndroid Build Coastguard Worker return;
33*3ac0a46fSAndroid Build Coastguard Worker }
34*3ac0a46fSAndroid Build Coastguard Worker CFWL_Widget::SetStates(dwStates);
35*3ac0a46fSAndroid Build Coastguard Worker }
36*3ac0a46fSAndroid Build Coastguard Worker
Update()37*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::Update() {
38*3ac0a46fSAndroid Build Coastguard Worker if (IsLocked())
39*3ac0a46fSAndroid Build Coastguard Worker return;
40*3ac0a46fSAndroid Build Coastguard Worker
41*3ac0a46fSAndroid Build Coastguard Worker m_ClientRect = GetClientRect();
42*3ac0a46fSAndroid Build Coastguard Worker m_CaptionRect = m_ClientRect;
43*3ac0a46fSAndroid Build Coastguard Worker }
44*3ac0a46fSAndroid Build Coastguard Worker
DrawWidget(CFGAS_GEGraphics * pGraphics,const CFX_Matrix & matrix)45*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::DrawWidget(CFGAS_GEGraphics* pGraphics,
46*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
47*3ac0a46fSAndroid Build Coastguard Worker if (!pGraphics)
48*3ac0a46fSAndroid Build Coastguard Worker return;
49*3ac0a46fSAndroid Build Coastguard Worker
50*3ac0a46fSAndroid Build Coastguard Worker if (HasBorder())
51*3ac0a46fSAndroid Build Coastguard Worker DrawBorder(pGraphics, CFWL_ThemePart::Part::kBorder, matrix);
52*3ac0a46fSAndroid Build Coastguard Worker
53*3ac0a46fSAndroid Build Coastguard Worker DrawBkground(pGraphics, matrix);
54*3ac0a46fSAndroid Build Coastguard Worker }
55*3ac0a46fSAndroid Build Coastguard Worker
DrawBkground(CFGAS_GEGraphics * pGraphics,const CFX_Matrix & matrix)56*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::DrawBkground(CFGAS_GEGraphics* pGraphics,
57*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
58*3ac0a46fSAndroid Build Coastguard Worker CFWL_ThemeBackground param(CFWL_ThemePart::Part::kBackground, this,
59*3ac0a46fSAndroid Build Coastguard Worker pGraphics);
60*3ac0a46fSAndroid Build Coastguard Worker param.m_dwStates = GetPartStates();
61*3ac0a46fSAndroid Build Coastguard Worker param.m_matrix = matrix;
62*3ac0a46fSAndroid Build Coastguard Worker param.m_PartRect = m_ClientRect;
63*3ac0a46fSAndroid Build Coastguard Worker if (m_Properties.m_dwStates & FWL_STATE_WGT_Focused)
64*3ac0a46fSAndroid Build Coastguard Worker param.m_pRtData = &m_CaptionRect;
65*3ac0a46fSAndroid Build Coastguard Worker GetThemeProvider()->DrawBackground(param);
66*3ac0a46fSAndroid Build Coastguard Worker }
67*3ac0a46fSAndroid Build Coastguard Worker
GetPartStates()68*3ac0a46fSAndroid Build Coastguard Worker Mask<CFWL_PartState> CFWL_PushButton::GetPartStates() {
69*3ac0a46fSAndroid Build Coastguard Worker Mask<CFWL_PartState> dwStates = CFWL_PartState::kNormal;
70*3ac0a46fSAndroid Build Coastguard Worker if (m_Properties.m_dwStates & FWL_STATE_WGT_Focused)
71*3ac0a46fSAndroid Build Coastguard Worker dwStates |= CFWL_PartState::kFocused;
72*3ac0a46fSAndroid Build Coastguard Worker if (m_Properties.m_dwStates & FWL_STATE_WGT_Disabled)
73*3ac0a46fSAndroid Build Coastguard Worker dwStates = CFWL_PartState::kDisabled;
74*3ac0a46fSAndroid Build Coastguard Worker else if (m_Properties.m_dwStates & FWL_STATE_PSB_Pressed)
75*3ac0a46fSAndroid Build Coastguard Worker dwStates |= CFWL_PartState::kPressed;
76*3ac0a46fSAndroid Build Coastguard Worker else if (m_Properties.m_dwStates & FWL_STATE_PSB_Hovered)
77*3ac0a46fSAndroid Build Coastguard Worker dwStates |= CFWL_PartState::kHovered;
78*3ac0a46fSAndroid Build Coastguard Worker return dwStates;
79*3ac0a46fSAndroid Build Coastguard Worker }
80*3ac0a46fSAndroid Build Coastguard Worker
OnProcessMessage(CFWL_Message * pMessage)81*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) {
82*3ac0a46fSAndroid Build Coastguard Worker if (!IsEnabled())
83*3ac0a46fSAndroid Build Coastguard Worker return;
84*3ac0a46fSAndroid Build Coastguard Worker
85*3ac0a46fSAndroid Build Coastguard Worker switch (pMessage->GetType()) {
86*3ac0a46fSAndroid Build Coastguard Worker case CFWL_Message::Type::kSetFocus:
87*3ac0a46fSAndroid Build Coastguard Worker OnFocusGained();
88*3ac0a46fSAndroid Build Coastguard Worker break;
89*3ac0a46fSAndroid Build Coastguard Worker case CFWL_Message::Type::kKillFocus:
90*3ac0a46fSAndroid Build Coastguard Worker OnFocusLost();
91*3ac0a46fSAndroid Build Coastguard Worker break;
92*3ac0a46fSAndroid Build Coastguard Worker case CFWL_Message::Type::kMouse: {
93*3ac0a46fSAndroid Build Coastguard Worker CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
94*3ac0a46fSAndroid Build Coastguard Worker switch (pMsg->m_dwCmd) {
95*3ac0a46fSAndroid Build Coastguard Worker case CFWL_MessageMouse::MouseCommand::kLeftButtonDown:
96*3ac0a46fSAndroid Build Coastguard Worker OnLButtonDown(pMsg);
97*3ac0a46fSAndroid Build Coastguard Worker break;
98*3ac0a46fSAndroid Build Coastguard Worker case CFWL_MessageMouse::MouseCommand::kLeftButtonUp:
99*3ac0a46fSAndroid Build Coastguard Worker OnLButtonUp(pMsg);
100*3ac0a46fSAndroid Build Coastguard Worker break;
101*3ac0a46fSAndroid Build Coastguard Worker case CFWL_MessageMouse::MouseCommand::kMove:
102*3ac0a46fSAndroid Build Coastguard Worker OnMouseMove(pMsg);
103*3ac0a46fSAndroid Build Coastguard Worker break;
104*3ac0a46fSAndroid Build Coastguard Worker case CFWL_MessageMouse::MouseCommand::kLeave:
105*3ac0a46fSAndroid Build Coastguard Worker OnMouseLeave(pMsg);
106*3ac0a46fSAndroid Build Coastguard Worker break;
107*3ac0a46fSAndroid Build Coastguard Worker default:
108*3ac0a46fSAndroid Build Coastguard Worker break;
109*3ac0a46fSAndroid Build Coastguard Worker }
110*3ac0a46fSAndroid Build Coastguard Worker break;
111*3ac0a46fSAndroid Build Coastguard Worker }
112*3ac0a46fSAndroid Build Coastguard Worker case CFWL_Message::Type::kKey: {
113*3ac0a46fSAndroid Build Coastguard Worker CFWL_MessageKey* pKey = static_cast<CFWL_MessageKey*>(pMessage);
114*3ac0a46fSAndroid Build Coastguard Worker if (pKey->m_dwCmd == CFWL_MessageKey::KeyCommand::kKeyDown)
115*3ac0a46fSAndroid Build Coastguard Worker OnKeyDown(pKey);
116*3ac0a46fSAndroid Build Coastguard Worker break;
117*3ac0a46fSAndroid Build Coastguard Worker }
118*3ac0a46fSAndroid Build Coastguard Worker default:
119*3ac0a46fSAndroid Build Coastguard Worker break;
120*3ac0a46fSAndroid Build Coastguard Worker }
121*3ac0a46fSAndroid Build Coastguard Worker // Dst target could be |this|, continue only if not destroyed by above.
122*3ac0a46fSAndroid Build Coastguard Worker if (pMessage->GetDstTarget())
123*3ac0a46fSAndroid Build Coastguard Worker CFWL_Widget::OnProcessMessage(pMessage);
124*3ac0a46fSAndroid Build Coastguard Worker }
125*3ac0a46fSAndroid Build Coastguard Worker
OnDrawWidget(CFGAS_GEGraphics * pGraphics,const CFX_Matrix & matrix)126*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnDrawWidget(CFGAS_GEGraphics* pGraphics,
127*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
128*3ac0a46fSAndroid Build Coastguard Worker DrawWidget(pGraphics, matrix);
129*3ac0a46fSAndroid Build Coastguard Worker }
130*3ac0a46fSAndroid Build Coastguard Worker
OnFocusGained()131*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnFocusGained() {
132*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_WGT_Focused;
133*3ac0a46fSAndroid Build Coastguard Worker RepaintRect(m_ClientRect);
134*3ac0a46fSAndroid Build Coastguard Worker }
135*3ac0a46fSAndroid Build Coastguard Worker
OnFocusLost()136*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnFocusLost() {
137*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_WGT_Focused;
138*3ac0a46fSAndroid Build Coastguard Worker RepaintRect(m_ClientRect);
139*3ac0a46fSAndroid Build Coastguard Worker }
140*3ac0a46fSAndroid Build Coastguard Worker
OnLButtonDown(CFWL_MessageMouse * pMsg)141*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnLButtonDown(CFWL_MessageMouse* pMsg) {
142*3ac0a46fSAndroid Build Coastguard Worker m_bBtnDown = true;
143*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_PSB_Hovered;
144*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_PSB_Pressed;
145*3ac0a46fSAndroid Build Coastguard Worker RepaintRect(m_ClientRect);
146*3ac0a46fSAndroid Build Coastguard Worker }
147*3ac0a46fSAndroid Build Coastguard Worker
OnLButtonUp(CFWL_MessageMouse * pMsg)148*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnLButtonUp(CFWL_MessageMouse* pMsg) {
149*3ac0a46fSAndroid Build Coastguard Worker m_bBtnDown = false;
150*3ac0a46fSAndroid Build Coastguard Worker if (m_ClientRect.Contains(pMsg->m_pos)) {
151*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Pressed;
152*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_PSB_Hovered;
153*3ac0a46fSAndroid Build Coastguard Worker } else {
154*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Hovered;
155*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Pressed;
156*3ac0a46fSAndroid Build Coastguard Worker }
157*3ac0a46fSAndroid Build Coastguard Worker if (m_ClientRect.Contains(pMsg->m_pos)) {
158*3ac0a46fSAndroid Build Coastguard Worker CFWL_Event wmClick(CFWL_Event::Type::Click, this);
159*3ac0a46fSAndroid Build Coastguard Worker DispatchEvent(&wmClick);
160*3ac0a46fSAndroid Build Coastguard Worker }
161*3ac0a46fSAndroid Build Coastguard Worker RepaintRect(m_ClientRect);
162*3ac0a46fSAndroid Build Coastguard Worker }
163*3ac0a46fSAndroid Build Coastguard Worker
OnMouseMove(CFWL_MessageMouse * pMsg)164*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnMouseMove(CFWL_MessageMouse* pMsg) {
165*3ac0a46fSAndroid Build Coastguard Worker bool bRepaint = false;
166*3ac0a46fSAndroid Build Coastguard Worker if (m_bBtnDown) {
167*3ac0a46fSAndroid Build Coastguard Worker if (m_ClientRect.Contains(pMsg->m_pos)) {
168*3ac0a46fSAndroid Build Coastguard Worker if ((m_Properties.m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
169*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_PSB_Pressed;
170*3ac0a46fSAndroid Build Coastguard Worker bRepaint = true;
171*3ac0a46fSAndroid Build Coastguard Worker }
172*3ac0a46fSAndroid Build Coastguard Worker if (m_Properties.m_dwStates & FWL_STATE_PSB_Hovered) {
173*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Hovered;
174*3ac0a46fSAndroid Build Coastguard Worker bRepaint = true;
175*3ac0a46fSAndroid Build Coastguard Worker }
176*3ac0a46fSAndroid Build Coastguard Worker } else {
177*3ac0a46fSAndroid Build Coastguard Worker if (m_Properties.m_dwStates & FWL_STATE_PSB_Pressed) {
178*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Pressed;
179*3ac0a46fSAndroid Build Coastguard Worker bRepaint = true;
180*3ac0a46fSAndroid Build Coastguard Worker }
181*3ac0a46fSAndroid Build Coastguard Worker if ((m_Properties.m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
182*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_PSB_Hovered;
183*3ac0a46fSAndroid Build Coastguard Worker bRepaint = true;
184*3ac0a46fSAndroid Build Coastguard Worker }
185*3ac0a46fSAndroid Build Coastguard Worker }
186*3ac0a46fSAndroid Build Coastguard Worker } else {
187*3ac0a46fSAndroid Build Coastguard Worker if (!m_ClientRect.Contains(pMsg->m_pos))
188*3ac0a46fSAndroid Build Coastguard Worker return;
189*3ac0a46fSAndroid Build Coastguard Worker if ((m_Properties.m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
190*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates |= FWL_STATE_PSB_Hovered;
191*3ac0a46fSAndroid Build Coastguard Worker bRepaint = true;
192*3ac0a46fSAndroid Build Coastguard Worker }
193*3ac0a46fSAndroid Build Coastguard Worker }
194*3ac0a46fSAndroid Build Coastguard Worker if (bRepaint)
195*3ac0a46fSAndroid Build Coastguard Worker RepaintRect(m_ClientRect);
196*3ac0a46fSAndroid Build Coastguard Worker }
197*3ac0a46fSAndroid Build Coastguard Worker
OnMouseLeave(CFWL_MessageMouse * pMsg)198*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnMouseLeave(CFWL_MessageMouse* pMsg) {
199*3ac0a46fSAndroid Build Coastguard Worker m_bBtnDown = false;
200*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Hovered;
201*3ac0a46fSAndroid Build Coastguard Worker m_Properties.m_dwStates &= ~FWL_STATE_PSB_Pressed;
202*3ac0a46fSAndroid Build Coastguard Worker RepaintRect(m_ClientRect);
203*3ac0a46fSAndroid Build Coastguard Worker }
204*3ac0a46fSAndroid Build Coastguard Worker
OnKeyDown(CFWL_MessageKey * pMsg)205*3ac0a46fSAndroid Build Coastguard Worker void CFWL_PushButton::OnKeyDown(CFWL_MessageKey* pMsg) {
206*3ac0a46fSAndroid Build Coastguard Worker if (pMsg->m_dwKeyCodeOrChar != XFA_FWL_VKEY_Return)
207*3ac0a46fSAndroid Build Coastguard Worker return;
208*3ac0a46fSAndroid Build Coastguard Worker
209*3ac0a46fSAndroid Build Coastguard Worker CFWL_EventMouse wmMouse(this, nullptr,
210*3ac0a46fSAndroid Build Coastguard Worker CFWL_MessageMouse::MouseCommand::kLeftButtonUp);
211*3ac0a46fSAndroid Build Coastguard Worker DispatchEvent(&wmMouse);
212*3ac0a46fSAndroid Build Coastguard Worker if (!wmMouse.GetSrcTarget())
213*3ac0a46fSAndroid Build Coastguard Worker return;
214*3ac0a46fSAndroid Build Coastguard Worker
215*3ac0a46fSAndroid Build Coastguard Worker CFWL_Event wmClick(CFWL_Event::Type::Click, this);
216*3ac0a46fSAndroid Build Coastguard Worker DispatchEvent(&wmClick);
217*3ac0a46fSAndroid Build Coastguard Worker }
218