Home | History | Annotate | Download | only in fwl
      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 
     23 CFWL_PushButton::CFWL_PushButton(const CFWL_App* app)
     24     : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
     25       m_bBtnDown(false) {}
     26 
     27 CFWL_PushButton::~CFWL_PushButton() {}
     28 
     29 FWL_Type CFWL_PushButton::GetClassID() const {
     30   return FWL_Type::PushButton;
     31 }
     32 
     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 
     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 
     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 
     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 
     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 
     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 
    139 void CFWL_PushButton::OnDrawWidget(CXFA_Graphics* pGraphics,
    140                                    const CFX_Matrix& matrix) {
    141   DrawWidget(pGraphics, matrix);
    142 }
    143 
    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 
    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 
    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 
    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 
    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 
    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