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/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 
     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 
     29 CFWL_PushButton::~CFWL_PushButton() {}
     30 
     31 FWL_Type CFWL_PushButton::GetClassID() const {
     32   return FWL_Type::PushButton;
     33 }
     34 
     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 
     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 
     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 
     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 
     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 
     97 void CFWL_PushButton::UpdateTextOutStyles() {
     98   m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
     99   m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
    100 }
    101 
    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 
    147 void CFWL_PushButton::OnDrawWidget(CFX_Graphics* pGraphics,
    148                                    const CFX_Matrix* pMatrix) {
    149   DrawWidget(pGraphics, pMatrix);
    150 }
    151 
    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 
    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 
    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 
    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 
    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 
    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