diff options
Diffstat (limited to 'xfa/fwl/basewidget/fwl_spinbuttonimp.cpp')
-rw-r--r-- | xfa/fwl/basewidget/fwl_spinbuttonimp.cpp | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/xfa/fwl/basewidget/fwl_spinbuttonimp.cpp b/xfa/fwl/basewidget/fwl_spinbuttonimp.cpp new file mode 100644 index 0000000000..9493cbbc7d --- /dev/null +++ b/xfa/fwl/basewidget/fwl_spinbuttonimp.cpp @@ -0,0 +1,429 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fwl/basewidget/fwl_spinbuttonimp.h" + +#include "xfa/fwl/core/fwl_noteimp.h" +#include "xfa/fwl/core/fwl_targetimp.h" +#include "xfa/fwl/core/fwl_widgetimp.h" +#include "xfa/include/fwl/basewidget/fwl_spinbutton.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/include/fwl/core/fwl_timer.h" + +#define FWL_SPN_MinWidth 18 +#define FWL_SPN_MinHeight 32 +#define FWL_SPIN_Elapse 200 + +// static +IFWL_SpinButton* IFWL_SpinButton::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_SpinButton* pSpinButton = new IFWL_SpinButton; + CFWL_SpinButtonImp* pSpinButtonImpl = + new CFWL_SpinButtonImp(properties, nullptr); + pSpinButton->SetImpl(pSpinButtonImpl); + pSpinButtonImpl->SetInterface(pSpinButton); + return pSpinButton; +} +IFWL_SpinButton::IFWL_SpinButton() {} +FWL_ERR IFWL_SpinButton::EnableButton(FX_BOOL bEnable, FX_BOOL bUp) { + return static_cast<CFWL_SpinButtonImp*>(GetImpl()) + ->EnableButton(bEnable, bUp); +} +FX_BOOL IFWL_SpinButton::IsButtonEnable(FX_BOOL bUp) { + return static_cast<CFWL_SpinButtonImp*>(GetImpl())->IsButtonEnable(bUp); +} + +CFWL_SpinButtonImp::CFWL_SpinButtonImp( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_dwUpState(FWL_PARTSTATE_SPB_Normal), + m_dwDnState(FWL_PARTSTATE_SPB_Normal), + m_iButtonIndex(0), + m_bLButtonDwn(FALSE), + m_hTimer(NULL) { + m_rtClient.Reset(); + m_rtUpButton.Reset(); + m_rtDnButton.Reset(); + m_pProperties->m_dwStyleExes |= FWL_STYLEEXE_SPB_Vert; +} +CFWL_SpinButtonImp::~CFWL_SpinButtonImp() {} +FWL_ERR CFWL_SpinButtonImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_SpinButton; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_SpinButtonImp::GetClassID() const { + return FWL_CLASSHASH_SpinButton; +} +FWL_ERR CFWL_SpinButtonImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_SpinButtonImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_SpinButtonImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_SpinButtonImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, FWL_SPN_MinWidth, FWL_SPN_MinHeight); + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_SpinButtonImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + GetClientRect(m_rtClient); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXE_SPB_Vert) { + m_rtUpButton.Set(m_rtClient.top, m_rtClient.left, m_rtClient.width, + m_rtClient.height / 2); + m_rtDnButton.Set(m_rtClient.left, m_rtClient.top + m_rtClient.height / 2, + m_rtClient.width, m_rtClient.height / 2); + } else { + m_rtUpButton.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width / 2, + m_rtClient.height); + m_rtDnButton.Set(m_rtClient.left + m_rtClient.width / 2, m_rtClient.top, + m_rtClient.width / 2, m_rtClient.height); + } + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_SpinButtonImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { + if (m_rtClient.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + if (HasBorder() && (m_rtClient.Contains(fx, fy))) { + return FWL_WGTHITTEST_Border; + } + if (HasEdge()) { + CFX_RectF rtEdge; + GetEdgeRect(rtEdge); + if (rtEdge.Contains(fx, fy)) { + return FWL_PART_SPB_Edge; + } + } + if (m_rtUpButton.Contains(fx, fy)) { + return FWL_WGTHITTEST_SPB_UpButton; + } + if (m_rtDnButton.Contains(fx, fy)) { + return FWL_WGTHITTEST_SPB_DownButton; + } + return FWL_WGTHITTEST_Unknown; +} +FWL_ERR CFWL_SpinButtonImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + CFX_RectF rtClip(m_rtClient); + if (pMatrix != NULL) { + pMatrix->TransformRect(rtClip); + } + IFWL_ThemeProvider* pTheme = GetAvailableTheme(); + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_SPB_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_SPB_Edge, pTheme, pMatrix); + } + DrawUpButton(pGraphics, pTheme, pMatrix); + DrawDownButton(pGraphics, pTheme, pMatrix); + return FWL_ERR_Succeeded; +} +int32_t CFWL_SpinButtonImp::Run(FWL_HTIMER hTimer) { + if (m_hTimer) { + CFWL_EvtSpbClick wmPosChanged; + wmPosChanged.m_pSrcTarget = m_pInterface; + wmPosChanged.m_bUp = m_iButtonIndex == 0; + DispatchEvent(&wmPosChanged); + } + return 1; +} +FWL_ERR CFWL_SpinButtonImp::EnableButton(FX_BOOL bEnable, FX_BOOL bUp) { + if (bUp) { + if (bEnable) { + m_dwUpState = FWL_PARTSTATE_SPB_Normal; + } else { + m_dwUpState = FWL_PARTSTATE_SPB_Disabled; + } + } else { + if (bEnable) { + m_dwDnState = FWL_PARTSTATE_SPB_Normal; + } else { + m_dwDnState = FWL_PARTSTATE_SPB_Disabled; + } + } + return FWL_ERR_Succeeded; +} +FX_BOOL CFWL_SpinButtonImp::IsButtonEnable(FX_BOOL bUp) { + if (bUp) { + return (m_dwUpState != FWL_PARTSTATE_SPB_Disabled); + } + return (m_dwDnState != FWL_PARTSTATE_SPB_Disabled); +} +void CFWL_SpinButtonImp::DrawUpButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_SPB_UpButton; + params.m_pGraphics = pGraphics; + params.m_dwStates = m_dwUpState + 1; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + params.m_rtPart = m_rtUpButton; + pTheme->DrawBackground(¶ms); +} +void CFWL_SpinButtonImp::DrawDownButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_SPB_DownButton; + params.m_pGraphics = pGraphics; + params.m_dwStates = m_dwDnState + 1; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + params.m_rtPart = m_rtDnButton; + pTheme->DrawBackground(¶ms); +} +CFWL_SpinButtonImpDelegate::CFWL_SpinButtonImpDelegate( + CFWL_SpinButtonImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_SpinButtonImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + int32_t iRet = 1; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + switch (dwMsgCode) { + case FWL_MSGHASH_SetFocus: + case FWL_MSGHASH_KillFocus: { + OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus); + break; + } + case FWL_MSGHASH_Mouse: { + CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); + FX_DWORD dwCmd = pMsg->m_dwCmd; + switch (dwCmd) { + case FWL_MSGMOUSECMD_LButtonDown: { + OnLButtonDown(pMsg); + break; + } + case FWL_MSGMOUSECMD_LButtonUp: { + OnLButtonUp(pMsg); + break; + } + case FWL_MSGMOUSECMD_MouseMove: { + OnMouseMove(pMsg); + break; + } + case FWL_MSGMOUSECMD_MouseLeave: { + OnMouseLeave(pMsg); + break; + } + default: {} + } + break; + } + case FWL_MSGHASH_Key: { + CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); + if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) { + OnKeyDown(pKey); + } + break; + } + default: { + iRet = 0; + break; + } + } + CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); + return iRet; +} +FWL_ERR CFWL_SpinButtonImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_SpinButtonImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_SpinButtonImpDelegate::OnFocusChanged(CFWL_Message* pMsg, + FX_BOOL bSet) { + if (bSet) { + m_pOwner->m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused); + } else { + m_pOwner->m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused); + } + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_SpinButtonImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + m_pOwner->m_bLButtonDwn = TRUE; + m_pOwner->SetGrab(TRUE); + m_pOwner->SetFocus(TRUE); + if (!m_pOwner->m_pProperties->m_pDataProvider) + return; + FX_BOOL bUpPress = (m_pOwner->m_rtUpButton.Contains(pMsg->m_fx, pMsg->m_fy) && + m_pOwner->IsButtonEnable(TRUE)); + FX_BOOL bDnPress = (m_pOwner->m_rtDnButton.Contains(pMsg->m_fx, pMsg->m_fy) && + m_pOwner->IsButtonEnable(FALSE)); + if (!bUpPress && !bDnPress) { + return; + } + if (bUpPress) { + m_pOwner->m_iButtonIndex = 0; + m_pOwner->m_dwUpState = FWL_PARTSTATE_SPB_Pressed; + } + if (bDnPress) { + m_pOwner->m_iButtonIndex = 1; + m_pOwner->m_dwDnState = FWL_PARTSTATE_SPB_Pressed; + } + CFWL_EvtSpbClick wmPosChanged; + wmPosChanged.m_pSrcTarget = m_pOwner->m_pInterface; + wmPosChanged.m_bUp = bUpPress; + m_pOwner->DispatchEvent(&wmPosChanged); + m_pOwner->Repaint(bUpPress ? &m_pOwner->m_rtUpButton + : &m_pOwner->m_rtDnButton); + m_pOwner->m_hTimer = FWL_StartTimer(m_pOwner, FWL_SPIN_Elapse); +} +void CFWL_SpinButtonImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pProperties->m_dwStates & FWL_PARTSTATE_SPB_Disabled) { + return; + } + m_pOwner->m_bLButtonDwn = FALSE; + m_pOwner->SetGrab(FALSE); + m_pOwner->SetFocus(FALSE); + if (m_pOwner->m_hTimer) { + FWL_StopTimer(m_pOwner->m_hTimer); + m_pOwner->m_hTimer = NULL; + } + FX_BOOL bRepaint = FALSE; + CFX_RectF rtInvalidate; + if (m_pOwner->m_dwUpState == FWL_PARTSTATE_SPB_Pressed && + m_pOwner->IsButtonEnable(TRUE)) { + m_pOwner->m_dwUpState = FWL_PARTSTATE_SPB_Normal; + bRepaint = TRUE; + rtInvalidate = m_pOwner->m_rtUpButton; + } else if (m_pOwner->m_dwDnState == FWL_PARTSTATE_SPB_Pressed && + m_pOwner->IsButtonEnable(FALSE)) { + m_pOwner->m_dwDnState = FWL_PARTSTATE_SPB_Normal; + bRepaint = TRUE; + rtInvalidate = m_pOwner->m_rtDnButton; + } + if (bRepaint) { + m_pOwner->Repaint(&rtInvalidate); + } +} +void CFWL_SpinButtonImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + if (!m_pOwner->m_pProperties->m_pDataProvider) + return; + if (m_pOwner->m_bLButtonDwn) { + return; + } + FX_BOOL bRepaint = FALSE; + CFX_RectF rtInvlidate; + rtInvlidate.Reset(); + if (m_pOwner->m_rtUpButton.Contains(pMsg->m_fx, pMsg->m_fy)) { + if (m_pOwner->IsButtonEnable(TRUE)) { + if (m_pOwner->m_dwUpState == FWL_PARTSTATE_SPB_Hovered) { + m_pOwner->m_dwUpState = FWL_PARTSTATE_SPB_Hovered; + bRepaint = TRUE; + rtInvlidate = m_pOwner->m_rtUpButton; + } + if (m_pOwner->m_dwDnState != FWL_PARTSTATE_SPB_Normal && + m_pOwner->IsButtonEnable(FALSE)) { + m_pOwner->m_dwDnState = FWL_PARTSTATE_SPB_Normal; + if (bRepaint) { + rtInvlidate.Union(m_pOwner->m_rtDnButton); + } else { + rtInvlidate = m_pOwner->m_rtDnButton; + } + bRepaint = TRUE; + } + } + if (!m_pOwner->IsButtonEnable(FALSE)) { + m_pOwner->EnableButton(FALSE, FALSE); + } + } else if (m_pOwner->m_rtDnButton.Contains(pMsg->m_fx, pMsg->m_fy)) { + if (m_pOwner->IsButtonEnable(FALSE)) { + if (m_pOwner->m_dwDnState != FWL_PARTSTATE_SPB_Hovered) { + m_pOwner->m_dwDnState = FWL_PARTSTATE_SPB_Hovered; + bRepaint = TRUE; + rtInvlidate = m_pOwner->m_rtDnButton; + } + if (m_pOwner->m_dwUpState != FWL_PARTSTATE_SPB_Normal && + m_pOwner->IsButtonEnable(TRUE)) { + m_pOwner->m_dwUpState = FWL_PARTSTATE_SPB_Normal; + if (bRepaint) { + rtInvlidate.Union(m_pOwner->m_rtUpButton); + } else { + rtInvlidate = m_pOwner->m_rtUpButton; + } + bRepaint = TRUE; + } + } + } else if (m_pOwner->m_dwUpState != FWL_PARTSTATE_SPB_Normal || + m_pOwner->m_dwDnState != FWL_PARTSTATE_SPB_Normal) { + if (m_pOwner->m_dwUpState != FWL_PARTSTATE_SPB_Normal) { + m_pOwner->m_dwUpState = FWL_PARTSTATE_SPB_Normal; + bRepaint = TRUE; + rtInvlidate = m_pOwner->m_rtUpButton; + } + if (m_pOwner->m_dwDnState != FWL_PARTSTATE_SPB_Normal) { + m_pOwner->m_dwDnState = FWL_PARTSTATE_SPB_Normal; + if (bRepaint) { + rtInvlidate.Union(m_pOwner->m_rtDnButton); + } else { + rtInvlidate = m_pOwner->m_rtDnButton; + } + bRepaint = TRUE; + } + } + if (bRepaint) { + m_pOwner->Repaint(&rtInvlidate); + } +} +void CFWL_SpinButtonImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { + if (!pMsg) + return; + if (m_pOwner->m_dwUpState != FWL_PARTSTATE_SPB_Normal && + m_pOwner->IsButtonEnable(TRUE)) { + m_pOwner->m_dwUpState = FWL_PARTSTATE_SPB_Normal; + } + if (m_pOwner->m_dwDnState != FWL_PARTSTATE_SPB_Normal && + m_pOwner->IsButtonEnable(FALSE)) { + m_pOwner->m_dwDnState = FWL_PARTSTATE_SPB_Normal; + } + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_SpinButtonImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) { + if (!m_pOwner->m_pProperties->m_pDataProvider) + return; + FX_BOOL bUp = + pMsg->m_dwKeyCode == FWL_VKEY_Up || pMsg->m_dwKeyCode == FWL_VKEY_Left; + FX_BOOL bDown = + pMsg->m_dwKeyCode == FWL_VKEY_Down || pMsg->m_dwKeyCode == FWL_VKEY_Right; + if (!bUp && !bDown) { + return; + } + FX_BOOL bUpEnable = m_pOwner->IsButtonEnable(TRUE); + FX_BOOL bDownEnable = m_pOwner->IsButtonEnable(FALSE); + if (!bUpEnable && !bDownEnable) { + return; + } + CFWL_EvtSpbClick wmPosChanged; + wmPosChanged.m_pSrcTarget = m_pOwner->m_pInterface; + wmPosChanged.m_bUp = bUpEnable; + m_pOwner->DispatchEvent(&wmPosChanged); + m_pOwner->Repaint(bUpEnable ? &m_pOwner->m_rtUpButton + : &m_pOwner->m_rtDnButton); +} |