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