• 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/tto/fde_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       m_dwTTOStyles(FDE_TTOSTYLE_SingleLine),
27       m_iTTOAlign(FDE_TTOALIGNMENT_Center) {}
28 
~CFWL_PushButton()29 CFWL_PushButton::~CFWL_PushButton() {}
30 
GetClassID() const31 FWL_Type CFWL_PushButton::GetClassID() const {
32   return FWL_Type::PushButton;
33 }
34 
SetStates(uint32_t dwStates)35 void CFWL_PushButton::SetStates(uint32_t dwStates) {
36   if (dwStates & FWL_WGTSTATE_Disabled) {
37     m_pProperties->m_dwStates = FWL_WGTSTATE_Disabled;
38     return;
39   }
40   CFWL_Widget::SetStates(dwStates);
41 }
42 
Update()43 void CFWL_PushButton::Update() {
44   if (IsLocked())
45     return;
46   if (!m_pProperties->m_pThemeProvider)
47     m_pProperties->m_pThemeProvider = GetAvailableTheme();
48 
49   UpdateTextOutStyles();
50   m_rtClient = GetClientRect();
51   m_rtCaption = m_rtClient;
52 }
53 
DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)54 void CFWL_PushButton::DrawWidget(CFX_Graphics* pGraphics,
55                                  const CFX_Matrix* pMatrix) {
56   if (!pGraphics)
57     return;
58   if (!m_pProperties->m_pThemeProvider)
59     return;
60 
61   if (HasBorder()) {
62     DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider,
63                pMatrix);
64   }
65   DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix);
66 }
67 
DrawBkground(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)68 void CFWL_PushButton::DrawBkground(CFX_Graphics* pGraphics,
69                                    IFWL_ThemeProvider* pTheme,
70                                    const CFX_Matrix* pMatrix) {
71   CFWL_ThemeBackground param;
72   param.m_pWidget = this;
73   param.m_iPart = CFWL_Part::Background;
74   param.m_dwStates = GetPartStates();
75   param.m_pGraphics = pGraphics;
76   if (pMatrix)
77     param.m_matrix.Concat(*pMatrix);
78   param.m_rtPart = m_rtClient;
79   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
80     param.m_pData = &m_rtCaption;
81   pTheme->DrawBackground(&param);
82 }
83 
GetPartStates()84 uint32_t CFWL_PushButton::GetPartStates() {
85   uint32_t dwStates = CFWL_PartState_Normal;
86   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
87     dwStates |= CFWL_PartState_Focused;
88   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
89     dwStates = CFWL_PartState_Disabled;
90   else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed)
91     dwStates |= CFWL_PartState_Pressed;
92   else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered)
93     dwStates |= CFWL_PartState_Hovered;
94   return dwStates;
95 }
96 
UpdateTextOutStyles()97 void CFWL_PushButton::UpdateTextOutStyles() {
98   m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
99   m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
100 }
101 
OnProcessMessage(CFWL_Message * pMessage)102 void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) {
103   if (!pMessage)
104     return;
105   if (!IsEnabled())
106     return;
107 
108   switch (pMessage->GetType()) {
109     case CFWL_Message::Type::SetFocus:
110       OnFocusChanged(pMessage, true);
111       break;
112     case CFWL_Message::Type::KillFocus:
113       OnFocusChanged(pMessage, false);
114       break;
115     case CFWL_Message::Type::Mouse: {
116       CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
117       switch (pMsg->m_dwCmd) {
118         case FWL_MouseCommand::LeftButtonDown:
119           OnLButtonDown(pMsg);
120           break;
121         case FWL_MouseCommand::LeftButtonUp:
122           OnLButtonUp(pMsg);
123           break;
124         case FWL_MouseCommand::Move:
125           OnMouseMove(pMsg);
126           break;
127         case FWL_MouseCommand::Leave:
128           OnMouseLeave(pMsg);
129           break;
130         default:
131           break;
132       }
133       break;
134     }
135     case CFWL_Message::Type::Key: {
136       CFWL_MessageKey* pKey = static_cast<CFWL_MessageKey*>(pMessage);
137       if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
138         OnKeyDown(pKey);
139       break;
140     }
141     default:
142       break;
143   }
144   CFWL_Widget::OnProcessMessage(pMessage);
145 }
146 
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)147 void CFWL_PushButton::OnDrawWidget(CFX_Graphics* pGraphics,
148                                    const CFX_Matrix* pMatrix) {
149   DrawWidget(pGraphics, pMatrix);
150 }
151 
OnFocusChanged(CFWL_Message * pMsg,bool bSet)152 void CFWL_PushButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
153   if (bSet)
154     m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
155   else
156     m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
157 
158   RepaintRect(m_rtClient);
159 }
160 
OnLButtonDown(CFWL_MessageMouse * pMsg)161 void CFWL_PushButton::OnLButtonDown(CFWL_MessageMouse* pMsg) {
162   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
163     SetFocus(true);
164 
165   m_bBtnDown = true;
166   m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
167   m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
168   RepaintRect(m_rtClient);
169 }
170 
OnLButtonUp(CFWL_MessageMouse * pMsg)171 void CFWL_PushButton::OnLButtonUp(CFWL_MessageMouse* pMsg) {
172   m_bBtnDown = false;
173   if (m_rtClient.Contains(pMsg->m_pos)) {
174     m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
175     m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
176   } else {
177     m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
178     m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
179   }
180   if (m_rtClient.Contains(pMsg->m_pos)) {
181     CFWL_Event wmClick(CFWL_Event::Type::Click, this);
182     DispatchEvent(&wmClick);
183   }
184   RepaintRect(m_rtClient);
185 }
186 
OnMouseMove(CFWL_MessageMouse * pMsg)187 void CFWL_PushButton::OnMouseMove(CFWL_MessageMouse* pMsg) {
188   bool bRepaint = false;
189   if (m_bBtnDown) {
190     if (m_rtClient.Contains(pMsg->m_pos)) {
191       if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
192         m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
193         bRepaint = true;
194       }
195       if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) {
196         m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
197         bRepaint = true;
198       }
199     } else {
200       if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) {
201         m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
202         bRepaint = true;
203       }
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   } else {
210     if (!m_rtClient.Contains(pMsg->m_pos))
211       return;
212     if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
213       m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
214       bRepaint = true;
215     }
216   }
217   if (bRepaint)
218     RepaintRect(m_rtClient);
219 }
220 
OnMouseLeave(CFWL_MessageMouse * pMsg)221 void CFWL_PushButton::OnMouseLeave(CFWL_MessageMouse* pMsg) {
222   m_bBtnDown = false;
223   m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
224   m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
225   RepaintRect(m_rtClient);
226 }
227 
OnKeyDown(CFWL_MessageKey * pMsg)228 void CFWL_PushButton::OnKeyDown(CFWL_MessageKey* pMsg) {
229   if (pMsg->m_dwKeyCode != FWL_VKEY_Return)
230     return;
231 
232   CFWL_EventMouse wmMouse(this);
233   wmMouse.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
234   DispatchEvent(&wmMouse);
235 
236   CFWL_Event wmClick(CFWL_Event::Type::Click, this);
237   DispatchEvent(&wmClick);
238 }
239