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