• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "xfa/fwl/cfwl_pushbutton.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "third_party/base/ptr_util.h"
13 #include "xfa/fde/cfde_textout.h"
14 #include "xfa/fwl/cfwl_event.h"
15 #include "xfa/fwl/cfwl_eventmouse.h"
16 #include "xfa/fwl/cfwl_messagekey.h"
17 #include "xfa/fwl/cfwl_messagemouse.h"
18 #include "xfa/fwl/cfwl_notedriver.h"
19 #include "xfa/fwl/cfwl_themebackground.h"
20 #include "xfa/fwl/cfwl_themetext.h"
21 #include "xfa/fwl/ifwl_themeprovider.h"
22 
CFWL_PushButton(const CFWL_App * app)23 CFWL_PushButton::CFWL_PushButton(const CFWL_App* app)
24     : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
25       m_bBtnDown(false) {}
26 
~CFWL_PushButton()27 CFWL_PushButton::~CFWL_PushButton() {}
28 
GetClassID() const29 FWL_Type CFWL_PushButton::GetClassID() const {
30   return FWL_Type::PushButton;
31 }
32 
SetStates(uint32_t dwStates)33 void CFWL_PushButton::SetStates(uint32_t dwStates) {
34   if (dwStates & FWL_WGTSTATE_Disabled) {
35     m_pProperties->m_dwStates = FWL_WGTSTATE_Disabled;
36     return;
37   }
38   CFWL_Widget::SetStates(dwStates);
39 }
40 
Update()41 void CFWL_PushButton::Update() {
42   if (IsLocked())
43     return;
44   if (!m_pProperties->m_pThemeProvider)
45     m_pProperties->m_pThemeProvider = GetAvailableTheme();
46 
47   m_rtClient = GetClientRect();
48   m_rtCaption = m_rtClient;
49 }
50 
DrawWidget(CXFA_Graphics * pGraphics,const CFX_Matrix & matrix)51 void CFWL_PushButton::DrawWidget(CXFA_Graphics* pGraphics,
52                                  const CFX_Matrix& matrix) {
53   if (!pGraphics)
54     return;
55   if (!m_pProperties->m_pThemeProvider)
56     return;
57 
58   if (HasBorder()) {
59     DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider,
60                matrix);
61   }
62   DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, &matrix);
63 }
64 
DrawBkground(CXFA_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)65 void CFWL_PushButton::DrawBkground(CXFA_Graphics* pGraphics,
66                                    IFWL_ThemeProvider* pTheme,
67                                    const CFX_Matrix* pMatrix) {
68   CFWL_ThemeBackground param;
69   param.m_pWidget = this;
70   param.m_iPart = CFWL_Part::Background;
71   param.m_dwStates = GetPartStates();
72   param.m_pGraphics = pGraphics;
73   if (pMatrix)
74     param.m_matrix.Concat(*pMatrix);
75   param.m_rtPart = m_rtClient;
76   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
77     param.m_pData = &m_rtCaption;
78   pTheme->DrawBackground(&param);
79 }
80 
GetPartStates()81 uint32_t CFWL_PushButton::GetPartStates() {
82   uint32_t dwStates = CFWL_PartState_Normal;
83   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
84     dwStates |= CFWL_PartState_Focused;
85   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
86     dwStates = CFWL_PartState_Disabled;
87   else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed)
88     dwStates |= CFWL_PartState_Pressed;
89   else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered)
90     dwStates |= CFWL_PartState_Hovered;
91   return dwStates;
92 }
93 
OnProcessMessage(CFWL_Message * pMessage)94 void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) {
95   if (!pMessage)
96     return;
97   if (!IsEnabled())
98     return;
99 
100   switch (pMessage->GetType()) {
101     case CFWL_Message::Type::SetFocus:
102       OnFocusChanged(pMessage, true);
103       break;
104     case CFWL_Message::Type::KillFocus:
105       OnFocusChanged(pMessage, false);
106       break;
107     case CFWL_Message::Type::Mouse: {
108       CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
109       switch (pMsg->m_dwCmd) {
110         case FWL_MouseCommand::LeftButtonDown:
111           OnLButtonDown(pMsg);
112           break;
113         case FWL_MouseCommand::LeftButtonUp:
114           OnLButtonUp(pMsg);
115           break;
116         case FWL_MouseCommand::Move:
117           OnMouseMove(pMsg);
118           break;
119         case FWL_MouseCommand::Leave:
120           OnMouseLeave(pMsg);
121           break;
122         default:
123           break;
124       }
125       break;
126     }
127     case CFWL_Message::Type::Key: {
128       CFWL_MessageKey* pKey = static_cast<CFWL_MessageKey*>(pMessage);
129       if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
130         OnKeyDown(pKey);
131       break;
132     }
133     default:
134       break;
135   }
136   CFWL_Widget::OnProcessMessage(pMessage);
137 }
138 
OnDrawWidget(CXFA_Graphics * pGraphics,const CFX_Matrix & matrix)139 void CFWL_PushButton::OnDrawWidget(CXFA_Graphics* pGraphics,
140                                    const CFX_Matrix& matrix) {
141   DrawWidget(pGraphics, matrix);
142 }
143 
OnFocusChanged(CFWL_Message * pMsg,bool bSet)144 void CFWL_PushButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
145   if (bSet)
146     m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
147   else
148     m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
149 
150   RepaintRect(m_rtClient);
151 }
152 
OnLButtonDown(CFWL_MessageMouse * pMsg)153 void CFWL_PushButton::OnLButtonDown(CFWL_MessageMouse* pMsg) {
154   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
155     SetFocus(true);
156 
157   m_bBtnDown = true;
158   m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
159   m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
160   RepaintRect(m_rtClient);
161 }
162 
OnLButtonUp(CFWL_MessageMouse * pMsg)163 void CFWL_PushButton::OnLButtonUp(CFWL_MessageMouse* pMsg) {
164   m_bBtnDown = false;
165   if (m_rtClient.Contains(pMsg->m_pos)) {
166     m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
167     m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
168   } else {
169     m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
170     m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
171   }
172   if (m_rtClient.Contains(pMsg->m_pos)) {
173     CFWL_Event wmClick(CFWL_Event::Type::Click, this);
174     DispatchEvent(&wmClick);
175   }
176   RepaintRect(m_rtClient);
177 }
178 
OnMouseMove(CFWL_MessageMouse * pMsg)179 void CFWL_PushButton::OnMouseMove(CFWL_MessageMouse* pMsg) {
180   bool bRepaint = false;
181   if (m_bBtnDown) {
182     if (m_rtClient.Contains(pMsg->m_pos)) {
183       if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
184         m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
185         bRepaint = true;
186       }
187       if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) {
188         m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
189         bRepaint = true;
190       }
191     } else {
192       if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) {
193         m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
194         bRepaint = true;
195       }
196       if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
197         m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
198         bRepaint = true;
199       }
200     }
201   } else {
202     if (!m_rtClient.Contains(pMsg->m_pos))
203       return;
204     if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
205       m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
206       bRepaint = true;
207     }
208   }
209   if (bRepaint)
210     RepaintRect(m_rtClient);
211 }
212 
OnMouseLeave(CFWL_MessageMouse * pMsg)213 void CFWL_PushButton::OnMouseLeave(CFWL_MessageMouse* pMsg) {
214   m_bBtnDown = false;
215   m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
216   m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
217   RepaintRect(m_rtClient);
218 }
219 
OnKeyDown(CFWL_MessageKey * pMsg)220 void CFWL_PushButton::OnKeyDown(CFWL_MessageKey* pMsg) {
221   if (pMsg->m_dwKeyCode != FWL_VKEY_Return)
222     return;
223 
224   CFWL_EventMouse wmMouse(this);
225   wmMouse.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
226   DispatchEvent(&wmMouse);
227 
228   CFWL_Event wmClick(CFWL_Event::Type::Click, this);
229   DispatchEvent(&wmClick);
230 }
231