diff options
author | Dan Sinclair <dsinclair@chromium.org> | 2016-03-08 12:16:00 -0500 |
---|---|---|
committer | Dan Sinclair <dsinclair@chromium.org> | 2016-03-08 12:16:00 -0500 |
commit | 6f6388fee1fdb4bec57549fe87a0833b2b20bebe (patch) | |
tree | 425b282da710e43904ebc68bf098a88cd2676397 /xfa/src/fwl/basewidget | |
parent | 71568591f4df8cc2d02fbd5544b0b0cc2b8f55e8 (diff) | |
download | pdfium-6f6388fee1fdb4bec57549fe87a0833b2b20bebe.tar.xz |
Remove xfa/src/fwl/src and move code up a level.
This Cl moves the xfa/src/fwl/src code up to the previously empty parent
directory and removes xfa/src/fwl/src.
R=tsepez@chromium.org
Review URL: https://codereview.chromium.org/1770953004 .
Diffstat (limited to 'xfa/src/fwl/basewidget')
30 files changed, 12810 insertions, 0 deletions
diff --git a/xfa/src/fwl/basewidget/fwl_barcodeimp.cpp b/xfa/src/fwl/basewidget/fwl_barcodeimp.cpp new file mode 100644 index 0000000000..af604f15a6 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_barcodeimp.cpp @@ -0,0 +1,221 @@ +// 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/src/fwl/basewidget/fwl_barcodeimp.h" + +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fwl/basewidget/fwl_editimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +// static +IFWL_Barcode* IFWL_Barcode::Create(const CFWL_WidgetImpProperties& properties) { + IFWL_Barcode* pBarcode = new IFWL_Barcode; + CFWL_BarcodeImp* pBarcodeImpl = new CFWL_BarcodeImp(properties, nullptr); + pBarcode->SetImpl(pBarcodeImpl); + pBarcodeImpl->SetInterface(pBarcode); + return pBarcode; +} +IFWL_Barcode::IFWL_Barcode() {} +void IFWL_Barcode::SetType(BC_TYPE type) { + static_cast<CFWL_BarcodeImp*>(GetImpl())->SetType(type); +} +FX_BOOL IFWL_Barcode::IsProtectedType() { + return static_cast<CFWL_BarcodeImp*>(GetImpl())->IsProtectedType(); +} + +CFWL_BarcodeImp::CFWL_BarcodeImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_EditImp(properties, pOuter), + m_pBarcodeEngine(NULL), + m_dwStatus(0), + m_type(BC_UNKNOWN) {} +CFWL_BarcodeImp::~CFWL_BarcodeImp() { + ReleaseBarcodeEngine(); +} +FWL_ERR CFWL_BarcodeImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_Barcode; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_BarcodeImp::GetClassID() const { + return FWL_CLASSHASH_Barcode; +} +FWL_ERR CFWL_BarcodeImp::Initialize() { + if (!m_pDelegate) { + m_pDelegate = new CFWL_BarcodeImpDelegate(this); + } + if (CFWL_EditImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_BarcodeImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + ReleaseBarcodeEngine(); + return CFWL_EditImp::Finalize(); +} +FWL_ERR CFWL_BarcodeImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + FWL_ERR ret = CFWL_EditImp::Update(); + GenerateBarcodeImageCache(); + return ret; +} +FWL_ERR CFWL_BarcodeImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + GenerateBarcodeImageCache(); + if (!m_pBarcodeEngine || (m_dwStatus & XFA_BCS_EncodeSuccess) == 0) { + return FWL_ERR_Succeeded; + } + CFX_Matrix mt; + mt.e = m_rtClient.left; + mt.f = m_rtClient.top; + if (pMatrix) { + mt.Concat(*pMatrix); + } + int32_t errorCode = 0; + if (!m_pBarcodeEngine->RenderDevice(pGraphics->GetRenderDevice(), pMatrix, + errorCode)) { + return FWL_ERR_Indefinite; + } + return FWL_ERR_Succeeded; + } + return CFWL_EditImp::DrawWidget(pGraphics, pMatrix); +} +void CFWL_BarcodeImp::GenerateBarcodeImageCache() { + if ((m_dwStatus & XFA_BCS_NeedUpdate) == 0) + return; + m_dwStatus = 0; + CreateBarcodeEngine(); + IFWL_BarcodeDP* pData = + static_cast<IFWL_BarcodeDP*>(m_pProperties->m_pDataProvider); + if (!pData) + return; + if (!m_pBarcodeEngine) + return; + CFX_WideString wsText; + if (GetText(wsText) != FWL_ERR_Succeeded) + return; + CFWL_ThemePart part; + part.m_pWidget = m_pInterface; + IFWL_ThemeProvider* pTheme = GetAvailableTheme(); + IFX_Font* pFont = + static_cast<IFX_Font*>(pTheme->GetCapacity(&part, FWL_WGTCAPACITY_Font)); + CFX_Font* pCXFont = + pFont ? static_cast<CFX_Font*>(pFont->GetDevFont()) : nullptr; + if (pCXFont) { + m_pBarcodeEngine->SetFont(pCXFont); + } + FX_FLOAT* pFontSize = static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_FontSize)); + if (pFontSize) { + m_pBarcodeEngine->SetFontSize(*pFontSize); + } + FX_ARGB* pFontColor = static_cast<FX_ARGB*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_TextColor)); + if (pFontColor) { + m_pBarcodeEngine->SetFontColor(*pFontColor); + } + m_pBarcodeEngine->SetHeight(int32_t(m_rtClient.height)); + m_pBarcodeEngine->SetWidth(int32_t(m_rtClient.width)); + FX_DWORD dwAttributeMask = pData->GetBarcodeAttributeMask(); + if (dwAttributeMask & FWL_BCDATTRIBUTE_CHARENCODING) { + m_pBarcodeEngine->SetCharEncoding(pData->GetCharEncoding()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_MODULEHEIGHT) { + m_pBarcodeEngine->SetModuleHeight(pData->GetModuleHeight()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_MODULEWIDTH) { + m_pBarcodeEngine->SetModuleWidth(pData->GetModuleWidth()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_DATALENGTH) { + m_pBarcodeEngine->SetDataLength(pData->GetDataLength()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_CALCHECKSUM) { + m_pBarcodeEngine->SetCalChecksum(pData->GetCalChecksum()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_PRINTCHECKSUM) { + m_pBarcodeEngine->SetPrintChecksum(pData->GetPrintChecksum()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_TEXTLOCATION) { + m_pBarcodeEngine->SetTextLocation(pData->GetTextLocation()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_WIDENARROWRATIO) { + m_pBarcodeEngine->SetWideNarrowRatio(pData->GetWideNarrowRatio()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_STARTCHAR) { + m_pBarcodeEngine->SetStartChar(pData->GetStartChar()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_ENDCHAR) { + m_pBarcodeEngine->SetEndChar(pData->GetEndChar()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_VERSION) { + m_pBarcodeEngine->SetVersion(pData->GetVersion()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_ECLEVEL) { + m_pBarcodeEngine->SetErrorCorrectionLevel(pData->GetErrorCorrectionLevel()); + } + if (dwAttributeMask & FWL_BCDATTRIBUTE_TRUNCATED) { + m_pBarcodeEngine->SetTruncated(pData->GetTruncated()); + } + int32_t errorCode = 0; + m_dwStatus = m_pBarcodeEngine->Encode(wsText, TRUE, errorCode) + ? XFA_BCS_EncodeSuccess + : 0; +} +void CFWL_BarcodeImp::CreateBarcodeEngine() { + if ((m_pBarcodeEngine == NULL) && (m_type != BC_UNKNOWN)) { + m_pBarcodeEngine = FX_Barcode_Create(m_type); + } +} +void CFWL_BarcodeImp::ReleaseBarcodeEngine() { + if (m_pBarcodeEngine) { + m_pBarcodeEngine->Release(); + m_pBarcodeEngine = NULL; + } +} +void CFWL_BarcodeImp::SetType(BC_TYPE type) { + if (m_type == type) { + return; + } + ReleaseBarcodeEngine(); + m_type = type; + m_dwStatus = XFA_BCS_NeedUpdate; +} +FWL_ERR CFWL_BarcodeImp::SetText(const CFX_WideString& wsText) { + ReleaseBarcodeEngine(); + m_dwStatus = XFA_BCS_NeedUpdate; + return CFWL_EditImp::SetText(wsText); +} +FX_BOOL CFWL_BarcodeImp::IsProtectedType() { + if (!m_pBarcodeEngine) { + return TRUE; + } + BC_TYPE tEngineType = m_pBarcodeEngine->GetType(); + if (tEngineType == BC_QR_CODE || tEngineType == BC_PDF417 || + tEngineType == BC_DATAMATRIX) { + return TRUE; + } + return FALSE; +} +CFWL_BarcodeImpDelegate::CFWL_BarcodeImpDelegate(CFWL_BarcodeImp* pOwner) + : CFWL_EditImpDelegate(pOwner) {} +FWL_ERR CFWL_BarcodeImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + FX_DWORD dwFlag = pEvent->GetClassID(); + if (dwFlag == FWL_EVTHASH_EDT_TextChanged) { + CFWL_BarcodeImp* pOwner = static_cast<CFWL_BarcodeImp*>(m_pOwner); + pOwner->ReleaseBarcodeEngine(); + pOwner->m_dwStatus = XFA_BCS_NeedUpdate; + } + return CFWL_EditImpDelegate::OnProcessEvent(pEvent); +} diff --git a/xfa/src/fwl/basewidget/fwl_barcodeimp.h b/xfa/src/fwl/basewidget/fwl_barcodeimp.h new file mode 100644 index 0000000000..eedcb16024 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_barcodeimp.h @@ -0,0 +1,54 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_BARCODEIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_BARCODEIMP_H_ + +#include "xfa/include/fwl/basewidget/fwl_barcode.h" +#include "xfa/include/fwl/basewidget/fwl_scrollbar.h" +#include "xfa/include/fwl/basewidget/fxmath_barcode.h" +#include "xfa/src/fwl/basewidget/fwl_editimp.h" + +class CFWL_WidgetImpProperties; +class CFWL_BarcodeImpDelegate; +class IFWL_Widget; + +#define XFA_BCS_NeedUpdate 0x0001 +#define XFA_BCS_EncodeSuccess 0x0002 + +class CFWL_BarcodeImp : public CFWL_EditImp { + public: + CFWL_BarcodeImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual ~CFWL_BarcodeImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual FWL_ERR SetText(const CFX_WideString& wsText); + virtual void SetType(BC_TYPE type); + FX_BOOL IsProtectedType(); + + protected: + void GenerateBarcodeImageCache(); + void CreateBarcodeEngine(); + void ReleaseBarcodeEngine(); + IFX_Barcode* m_pBarcodeEngine; + FX_DWORD m_dwStatus; + BC_TYPE m_type; + friend class CFWL_BarcodeImpDelegate; +}; + +class CFWL_BarcodeImpDelegate : public CFWL_EditImpDelegate { + public: + CFWL_BarcodeImpDelegate(CFWL_BarcodeImp* pOwner); + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_BARCODEIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_caretimp.cpp b/xfa/src/fwl/basewidget/fwl_caretimp.cpp new file mode 100644 index 0000000000..752f889dcf --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_caretimp.cpp @@ -0,0 +1,157 @@ +// 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/src/fwl/basewidget/fwl_caretimp.h" + +#include "xfa/include/fwl/basewidget/fwl_caret.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +// static +IFWL_Caret* IFWL_Caret::Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_Caret* pCaret = new IFWL_Caret; + CFWL_CaretImp* pCaretImpl = new CFWL_CaretImp(properties, pOuter); + pCaret->SetImpl(pCaretImpl); + pCaretImpl->SetInterface(pCaret); + return pCaret; +} +IFWL_Caret::IFWL_Caret() {} +FWL_ERR IFWL_Caret::ShowCaret(FX_BOOL bFlag) { + return static_cast<CFWL_CaretImp*>(GetImpl())->ShowCaret(bFlag); +} +FWL_ERR IFWL_Caret::GetFrequency(FX_DWORD& elapse) { + return static_cast<CFWL_CaretImp*>(GetImpl())->GetFrequency(elapse); +} +FWL_ERR IFWL_Caret::SetFrequency(FX_DWORD elapse) { + return static_cast<CFWL_CaretImp*>(GetImpl())->SetFrequency(elapse); +} +FWL_ERR IFWL_Caret::SetColor(CFX_Color crFill) { + return static_cast<CFWL_CaretImp*>(GetImpl())->SetColor(crFill); +} + +CFWL_CaretImp::CFWL_CaretImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_hTimer(nullptr), + m_dwElapse(400), + m_bSetColor(FALSE) { + m_pTimer = new CFWL_CaretTimer(this); + SetStates(FWL_STATE_CAT_HightLight); +} +CFWL_CaretImp::~CFWL_CaretImp() { + if (m_pTimer) { + delete m_pTimer; + m_pTimer = NULL; + } +} +FWL_ERR CFWL_CaretImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_Caret; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_CaretImp::GetClassID() const { + return FWL_CLASSHASH_Caret; +} +FWL_ERR CFWL_CaretImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_CaretImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CaretImp::Finalize() { + if (m_hTimer) { + FWL_StopTimer(m_hTimer); + m_hTimer = NULL; + } + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_CaretImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + DrawCaretBK(pGraphics, m_pProperties->m_pThemeProvider, pMatrix); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CaretImp::ShowCaret(FX_BOOL bFlag) { + if (m_hTimer) { + FWL_StopTimer(m_hTimer); + m_hTimer = NULL; + } + if (bFlag) { + m_hTimer = FWL_StartTimer(m_pTimer, m_dwElapse); + } + return SetStates(FWL_WGTSTATE_Invisible, !bFlag); +} +FWL_ERR CFWL_CaretImp::GetFrequency(FX_DWORD& elapse) { + elapse = m_dwElapse; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CaretImp::SetFrequency(FX_DWORD elapse) { + m_dwElapse = elapse; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CaretImp::SetColor(CFX_Color crFill) { + m_bSetColor = TRUE; + m_crFill = crFill; + return FWL_ERR_Succeeded; +} +FX_BOOL CFWL_CaretImp::DrawCaretBK(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFX_RectF rect; + GetWidgetRect(rect); + rect.Set(0, 0, rect.width, rect.height); + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_pGraphics = pGraphics; + param.m_rtPart = rect; + if (m_bSetColor) { + param.m_pData = &m_crFill; + } + if (!(m_pProperties->m_dwStates & FWL_STATE_CAT_HightLight)) { + return FWL_ERR_Succeeded; + } + param.m_iPart = FWL_PART_CAT_Background; + param.m_dwStates = FWL_PARTSTATE_CAT_HightLight; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶m); + return FWL_ERR_Succeeded; +} + +CFWL_CaretImp::CFWL_CaretTimer::CFWL_CaretTimer(CFWL_CaretImp* pCaret) + : m_pCaret(pCaret) {} + +int32_t CFWL_CaretImp::CFWL_CaretTimer::Run(FWL_HTIMER hTimer) { + if (m_pCaret->GetStates() & FWL_STATE_CAT_HightLight) { + m_pCaret->SetStates(FWL_STATE_CAT_HightLight, FALSE); + } else { + m_pCaret->SetStates(FWL_STATE_CAT_HightLight); + } + CFX_RectF rt; + m_pCaret->GetWidgetRect(rt); + rt.Set(0, 0, rt.width + 1, rt.height); + m_pCaret->Repaint(&rt); + return 1; +} +CFWL_CaretImpDelegate::CFWL_CaretImpDelegate(CFWL_CaretImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_CaretImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + return 1; +} +FWL_ERR CFWL_CaretImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} diff --git a/xfa/src/fwl/basewidget/fwl_caretimp.h b/xfa/src/fwl/basewidget/fwl_caretimp.h new file mode 100644 index 0000000000..e3dde63ab6 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_caretimp.h @@ -0,0 +1,67 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_CARETIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_CARETIMP_H_ + +#include "xfa/include/fwl/core/fwl_timer.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_CaretImpDelegate; + +class CFWL_CaretImp : public CFWL_WidgetImp { + public: + CFWL_CaretImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual ~CFWL_CaretImp(); + + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + + virtual FWL_ERR ShowCaret(FX_BOOL bFlag = TRUE); + virtual FWL_ERR GetFrequency(FX_DWORD& elapse); + virtual FWL_ERR SetFrequency(FX_DWORD elapse); + virtual FWL_ERR SetColor(CFX_Color crFill); + + protected: + FX_BOOL DrawCaretBK(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + class CFWL_CaretTimer : public IFWL_Timer { + public: + explicit CFWL_CaretTimer(CFWL_CaretImp* pCaret); + ~CFWL_CaretTimer() override {} + int32_t Run(FWL_HTIMER hTimer) override; + CFWL_CaretImp* const m_pCaret; + }; + CFWL_CaretTimer* m_pTimer; + FWL_HTIMER m_hTimer; + FX_DWORD m_dwElapse; + CFX_Color m_crFill; + FX_BOOL m_bSetColor; + friend class CFWL_CaretImpDelegate; + friend class CFWL_CaretTimer; +}; +class CFWL_CaretImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_CaretImpDelegate(CFWL_CaretImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + CFWL_CaretImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_CARETIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_checkboximp.cpp b/xfa/src/fwl/basewidget/fwl_checkboximp.cpp new file mode 100644 index 0000000000..ba9f0fedc3 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_checkboximp.cpp @@ -0,0 +1,555 @@ +// 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/src/fwl/basewidget/fwl_checkboximp.h" + +#include <algorithm> + +#include "xfa/include/fwl/basewidget/fwl_checkbox.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fdp/include/fde_tto.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" +#include "xfa/src/fwl/core/fwl_widgetmgrimp.h" + +#define FWL_CKB_CaptionMargin 5 + +// static +IFWL_CheckBox* IFWL_CheckBox::Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_CheckBox* pCheckBox = new IFWL_CheckBox; + CFWL_CheckBoxImp* pCheckBoxImpl = new CFWL_CheckBoxImp(properties, pOuter); + pCheckBox->SetImpl(pCheckBoxImpl); + pCheckBoxImpl->SetInterface(pCheckBox); + return pCheckBox; +} +IFWL_CheckBox::IFWL_CheckBox() {} +int32_t IFWL_CheckBox::GetCheckState() { + return static_cast<CFWL_CheckBoxImp*>(GetImpl())->GetCheckState(); +} +FWL_ERR IFWL_CheckBox::SetCheckState(int32_t iCheck) { + return static_cast<CFWL_CheckBoxImp*>(GetImpl())->SetCheckState(iCheck); +} + +CFWL_CheckBoxImp::CFWL_CheckBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_dwTTOStyles(FDE_TTOSTYLE_SingleLine), + m_iTTOAlign(FDE_TTOALIGNMENT_Center), + m_bBtnDown(FALSE) { + m_rtClient.Reset(); + m_rtBox.Reset(); + m_rtCaption.Reset(); + m_rtFocus.Reset(); +} +CFWL_CheckBoxImp::~CFWL_CheckBoxImp() {} +FWL_ERR CFWL_CheckBoxImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_CheckBox; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_CheckBoxImp::GetClassID() const { + return FWL_CLASSHASH_CheckBox; +} +FWL_ERR CFWL_CheckBoxImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_CheckBoxImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CheckBoxImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_CheckBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + if (!m_pProperties->m_pThemeProvider) + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pDataProvider) + return FWL_ERR_Indefinite; + CFX_WideString wsCaption; + m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption); + if (wsCaption.GetLength() > 0) { + CFX_SizeF sz = CalcTextSize( + wsCaption, m_pProperties->m_pThemeProvider, + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine); + rect.Set(0, 0, sz.x, sz.y); + } + rect.Inflate(FWL_CKB_CaptionMargin, FWL_CKB_CaptionMargin); + IFWL_CheckBoxDP* pData = + static_cast<IFWL_CheckBoxDP*>(m_pProperties->m_pDataProvider); + FX_FLOAT fCheckBox = pData->GetBoxSize(m_pInterface); + rect.width += fCheckBox; + if (rect.height < fCheckBox) { + rect.height = fCheckBox; + } + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CheckBoxImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + UpdateTextOutStyles(); + Layout(); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_CheckBoxImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_CKB_Border, m_pProperties->m_pThemeProvider, + pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_CKB_Edge, pTheme, pMatrix); + } + int32_t dwStates = GetPartStates(); + { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_CKB_Background; + param.m_dwStates = dwStates; + param.m_pGraphics = pGraphics; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = m_rtClient; + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + param.m_pData = &m_rtFocus; + } + pTheme->DrawBackground(¶m); + param.m_iPart = FWL_PART_CKB_CheckBox; + param.m_rtPart = m_rtBox; + pTheme->DrawBackground(¶m); + } + if (!m_pProperties->m_pDataProvider) + return FWL_ERR_Indefinite; + { + CFX_WideString wsCaption; + m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption); + int32_t iLen = wsCaption.GetLength(); + if (iLen <= 0) + return FWL_ERR_Indefinite; + CFWL_ThemeText textParam; + textParam.m_pWidget = m_pInterface; + textParam.m_iPart = FWL_PART_CKB_Caption; + textParam.m_dwStates = dwStates; + textParam.m_pGraphics = pGraphics; + if (pMatrix) { + textParam.m_matrix.Concat(*pMatrix); + } + textParam.m_rtPart = m_rtCaption; + textParam.m_wsText = wsCaption; + textParam.m_dwTTOStyles = m_dwTTOStyles; + textParam.m_iTTOAlign = m_iTTOAlign; + pTheme->DrawText(&textParam); + } + return FWL_ERR_Succeeded; +} +int32_t CFWL_CheckBoxImp::GetCheckState() { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) && + ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Neutral)) { + return 2; + } + if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Checked) { + return 1; + } + return 0; +} +FWL_ERR CFWL_CheckBoxImp::SetCheckState(int32_t iCheck) { + m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask; + switch (iCheck) { + case 0: { + break; + } + case 1: { + m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked; + break; + } + case 2: { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) { + m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral; + } + break; + } + default: {} + } + Repaint(&m_rtClient); + return FWL_ERR_Succeeded; +} +void CFWL_CheckBoxImp::Layout() { + int32_t width = int32_t(m_pProperties->m_rtWidget.width + 0.5f); + int32_t height = int32_t(m_pProperties->m_rtWidget.height + 0.5f); + m_pProperties->m_rtWidget.width = (FX_FLOAT)width; + m_pProperties->m_rtWidget.height = (FX_FLOAT)height; + GetClientRect(m_rtClient); + FX_FLOAT fBoxTop = m_rtClient.top; + FX_FLOAT fBoxLeft = m_rtClient.left; + FX_FLOAT fTextLeft = 0.0, fTextRight = 0.0; + FX_FLOAT fClientRight = m_rtClient.right(); + FX_FLOAT fClientBottom = m_rtClient.bottom(); + if (!m_pProperties->m_pDataProvider) + return; + IFWL_CheckBoxDP* pData = + static_cast<IFWL_CheckBoxDP*>(m_pProperties->m_pDataProvider); + FX_FLOAT fCheckBox = pData->GetBoxSize(m_pInterface); + switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) { + case FWL_STYLEEXT_CKB_Top: { + fBoxTop = m_rtClient.top; + break; + } + case FWL_STYLEEXT_CKB_Bottom: { + fBoxTop = fClientBottom - fCheckBox; + break; + } + case FWL_STYLEEXT_CKB_VCenter: + default: { + fBoxTop = m_rtClient.top + (m_rtClient.height - fCheckBox) / 2; + fBoxTop = FXSYS_floor(fBoxTop); + } + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_LeftText) { + fBoxLeft = fClientRight - fCheckBox; + fTextLeft = m_rtClient.left; + fTextRight = fBoxLeft; + } else { + fTextLeft = fBoxLeft + fCheckBox; + fTextRight = fClientRight; + } + m_rtBox.Set(fBoxLeft, fBoxTop, fCheckBox, fCheckBox); + m_rtCaption.Set(fTextLeft, m_rtClient.top, fTextRight - fTextLeft, + m_rtClient.height); + m_rtCaption.Inflate(-FWL_CKB_CaptionMargin, -FWL_CKB_CaptionMargin); + CFX_RectF rtFocus; + rtFocus.Set(m_rtCaption.left, m_rtCaption.top, m_rtCaption.width, + m_rtCaption.height); + CFX_WideString wsCaption; + m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption); + if (wsCaption.IsEmpty()) { + m_rtFocus.Set(0, 0, 0, 0); + } else { + CalcTextRect(wsCaption, m_pProperties->m_pThemeProvider, m_dwTTOStyles, + m_iTTOAlign, rtFocus); + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine) == 0) { + FX_FLOAT fWidth = std::max(m_rtCaption.width, rtFocus.width); + FX_FLOAT fHeight = std::min(m_rtCaption.height, rtFocus.height); + FX_FLOAT fLeft = m_rtCaption.left; + FX_FLOAT fTop = m_rtCaption.top; + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) == + FWL_STYLEEXT_CKB_Center) { + fLeft = m_rtCaption.left + (m_rtCaption.width - fWidth) / 2; + } else if ((m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_CKB_HLayoutMask) == FWL_STYLEEXT_CKB_Right) { + fLeft = m_rtCaption.right() - fWidth; + } + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) == + FWL_STYLEEXT_CKB_VCenter) { + fTop = m_rtCaption.top + (m_rtCaption.height - fHeight) / 2; + } else if ((m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_CKB_VLayoutMask) == FWL_STYLEEXT_CKB_Bottom) { + fTop = m_rtCaption.bottom() - fHeight; + } + m_rtFocus.Set(fLeft, fTop, fWidth, fHeight); + } else { + m_rtFocus.Set(rtFocus.left, rtFocus.top, rtFocus.width, rtFocus.height); + } + m_rtFocus.Inflate(1, 1); + } +} +FX_DWORD CFWL_CheckBoxImp::GetPartStates() { + int32_t dwStates = FWL_PARTSTATE_CKB_UnChecked; + if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Neutral) { + dwStates = FWL_PARTSTATE_CKB_Neutral; + } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Checked) { + dwStates = FWL_PARTSTATE_CKB_Checked; + } + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + dwStates |= FWL_PARTSTATE_CKB_Disabled; + } else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) { + dwStates |= FWL_PARTSTATE_CKB_Hovered; + } else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) { + dwStates |= FWL_PARTSTATE_CKB_Pressed; + } else { + dwStates |= FWL_PARTSTATE_CKB_Normal; + } + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + dwStates |= FWL_PARTSTATE_CKB_Focused; + } + return dwStates; +} +void CFWL_CheckBoxImp::UpdateTextOutStyles() { + m_iTTOAlign = FDE_TTOALIGNMENT_Center; + switch (m_pProperties->m_dwStyleExes & + (FWL_STYLEEXT_CKB_HLayoutMask | FWL_STYLEEXT_CKB_VLayoutMask)) { + case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Top: { + m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft; + break; + } + case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Top: { + m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter; + break; + } + case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Top: { + m_iTTOAlign = FDE_TTOALIGNMENT_TopRight; + break; + } + case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_VCenter: { + m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + break; + } + case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_VCenter: { + m_iTTOAlign = FDE_TTOALIGNMENT_Center; + break; + } + case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_VCenter: { + m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight; + break; + } + case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Bottom: { + m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft; + break; + } + case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Bottom: { + m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter; + break; + } + case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Bottom: { + m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight; + break; + } + default: {} + } + m_dwTTOStyles = 0; + if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) { + m_dwTTOStyles |= FDE_TTOSTYLE_RTL; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine) { + m_dwTTOStyles |= FDE_TTOSTYLE_LineWrap; + } else { + m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine; + } +} +void CFWL_CheckBoxImp::NextStates() { + FX_DWORD dwFirststate = m_pProperties->m_dwStates; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_RadioButton) { + if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Unchecked) { + CFWL_WidgetMgr* pWidgetMgr = + static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr()); + if (!pWidgetMgr->IsFormDisabled()) { + CFX_PtrArray radioarr; + pWidgetMgr->GetSameGroupRadioButton(m_pInterface, radioarr); + IFWL_CheckBox* pCheckBox = NULL; + int32_t iCount = radioarr.GetSize(); + for (int32_t i = 0; i < iCount; i++) { + pCheckBox = static_cast<IFWL_CheckBox*>(radioarr[i]); + if (pCheckBox != m_pInterface && + pCheckBox->GetStates() & FWL_STATE_CKB_Checked) { + pCheckBox->SetCheckState(0); + CFX_RectF rt; + pCheckBox->GetWidgetRect(rt); + rt.left = rt.top = 0; + m_pWidgetMgr->RepaintWidget(pCheckBox, &rt); + break; + } + } + } + m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked; + } + } else { + if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Neutral) { + m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) { + m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked; + } + } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == + FWL_STATE_CKB_Checked) { + m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask; + } else { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) { + m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral; + } else { + m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked; + } + } + } + Repaint(&m_rtClient); + FX_DWORD dwLaststate = m_pProperties->m_dwStates; + if (dwFirststate != dwLaststate) { + CFWL_EvtCkbCheckStateChanged wmCheckBoxState; + wmCheckBoxState.m_pSrcTarget = m_pInterface; + DispatchEvent(&wmCheckBoxState); + } +} +CFWL_CheckBoxImpDelegate::CFWL_CheckBoxImpDelegate(CFWL_CheckBoxImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_CheckBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + int32_t iRet = 1; + switch (dwMsgCode) { + case FWL_MSGHASH_Activate: { + OnActivate(pMessage); + break; + } + 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; } + } + CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); + return iRet; +} +FWL_ERR CFWL_CheckBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_CheckBoxImpDelegate::OnActivate(CFWL_Message* pMsg) { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Deactivated; + m_pOwner->Repaint(&(m_pOwner->m_rtClient)); +} +void CFWL_CheckBoxImpDelegate::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_CheckBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + return; + } + if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + m_pOwner->SetFocus(TRUE); + } + m_pOwner->m_bBtnDown = TRUE; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed; + m_pOwner->Repaint(&(m_pOwner->m_rtClient)); +} +void CFWL_CheckBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + if (!m_pOwner->m_bBtnDown) { + return; + } + m_pOwner->m_bBtnDown = FALSE; + if (!m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + return; + } + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed; + m_pOwner->NextStates(); +} +void CFWL_CheckBoxImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + return; + } + FX_BOOL bRepaint = FALSE; + if (m_pOwner->m_bBtnDown) { + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) == 0) { + bRepaint = TRUE; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed; + } + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered)) { + bRepaint = TRUE; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered; + } + } else { + if (m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) { + bRepaint = TRUE; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed; + } + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) { + bRepaint = TRUE; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered; + } + } + } else { + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) { + bRepaint = TRUE; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered; + } + } + } + if (bRepaint) { + m_pOwner->Repaint(&(m_pOwner->m_rtBox)); + } +} +void CFWL_CheckBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_bBtnDown) { + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered; + } else { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered; + } + m_pOwner->Repaint(&(m_pOwner->m_rtBox)); +} +void CFWL_CheckBoxImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) { + if (pMsg->m_dwKeyCode == FWL_VKEY_Tab) { + m_pOwner->DispatchKeyEvent(pMsg); + return; + } + if (pMsg->m_dwKeyCode == FWL_VKEY_Return || + pMsg->m_dwKeyCode == FWL_VKEY_Space) { + m_pOwner->NextStates(); + } +} diff --git a/xfa/src/fwl/basewidget/fwl_checkboximp.h b/xfa/src/fwl/basewidget/fwl_checkboximp.h new file mode 100644 index 0000000000..98702aaa59 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_checkboximp.h @@ -0,0 +1,64 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_CHECKBOXIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_CHECKBOXIMP_H_ + +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_CheckBoxImpDelegate; + +class CFWL_CheckBoxImp : public CFWL_WidgetImp { + public: + CFWL_CheckBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_CheckBoxImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual int32_t GetCheckState(); + virtual FWL_ERR SetCheckState(int32_t iCheck); + + protected: + void Layout(); + FX_DWORD GetPartStates(); + void UpdateTextOutStyles(); + void NextStates(); + CFX_RectF m_rtClient; + CFX_RectF m_rtBox; + CFX_RectF m_rtCaption; + CFX_RectF m_rtFocus; + FX_DWORD m_dwTTOStyles; + int32_t m_iTTOAlign; + FX_BOOL m_bBtnDown; + friend class CFWL_CheckBoxImpDelegate; +}; +class CFWL_CheckBoxImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_CheckBoxImpDelegate(CFWL_CheckBoxImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnActivate(CFWL_Message* pMsg); + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + void OnKeyDown(CFWL_MsgKey* pMsg); + CFWL_CheckBoxImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_CHECKBOXIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_comboboximp.cpp b/xfa/src/fwl/basewidget/fwl_comboboximp.cpp new file mode 100644 index 0000000000..842ab8aaa9 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_comboboximp.cpp @@ -0,0 +1,1819 @@ +// 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/src/fwl/basewidget/fwl_comboboximp.h" + +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fdp/include/fde_tto.h" +#include "xfa/src/fwl/basewidget/fwl_editimp.h" +#include "xfa/src/fwl/basewidget/fwl_formproxyimp.h" +#include "xfa/src/fwl/basewidget/fwl_listboximp.h" +#include "xfa/src/fwl/basewidget/fwl_scrollbarimp.h" +#include "xfa/src/fwl/core/fwl_appimp.h" +#include "xfa/src/fwl/core/fwl_formimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_panelimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_threadimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" +#include "xfa/src/fwl/core/fwl_widgetmgrimp.h" + +// static +IFWL_ComboBox* IFWL_ComboBox::Create( + const CFWL_WidgetImpProperties& properties) { + IFWL_ComboBox* pComboBox = new IFWL_ComboBox; + CFWL_ComboBoxImp* pComboBoxImpl = new CFWL_ComboBoxImp(properties, nullptr); + pComboBox->SetImpl(pComboBoxImpl); + pComboBoxImpl->SetInterface(pComboBox); + return pComboBox; +} +IFWL_ComboBox::IFWL_ComboBox() {} +int32_t IFWL_ComboBox::GetCurSel() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetCurSel(); +} +FWL_ERR IFWL_ComboBox::SetCurSel(int32_t iSel) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetCurSel(iSel); +} +FWL_ERR IFWL_ComboBox::SetEditText(const CFX_WideString& wsText) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditText(wsText); +} +int32_t IFWL_ComboBox::GetEditTextLength() const { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditTextLength(); +} +FWL_ERR IFWL_ComboBox::GetEditText(CFX_WideString& wsText, + int32_t nStart, + int32_t nCount) const { + return static_cast<CFWL_ComboBoxImp*>(GetImpl()) + ->GetEditText(wsText, nStart, nCount); +} +FWL_ERR IFWL_ComboBox::SetEditSelRange(int32_t nStart, int32_t nCount) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl()) + ->SetEditSelRange(nStart, nCount); +} +int32_t IFWL_ComboBox::GetEditSelRange(int32_t nIndex, int32_t& nStart) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl()) + ->GetEditSelRange(nIndex, nStart); +} +int32_t IFWL_ComboBox::GetEditLimit() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditLimit(); +} +FWL_ERR IFWL_ComboBox::SetEditLimit(int32_t nLimit) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditLimit(nLimit); +} +FWL_ERR IFWL_ComboBox::EditDoClipboard(int32_t iCmd) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDoClipboard(iCmd); +} +FX_BOOL IFWL_ComboBox::EditRedo(const CFX_ByteStringC& bsRecord) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo(bsRecord); +} +FX_BOOL IFWL_ComboBox::EditUndo(const CFX_ByteStringC& bsRecord) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo(bsRecord); +} +IFWL_ListBox* IFWL_ComboBox::GetListBoxt() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetListBoxt(); +} +FX_BOOL IFWL_ComboBox::AfterFocusShowDropList() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->AfterFocusShowDropList(); +} +FX_ERR IFWL_ComboBox::OpenDropDownList(FX_BOOL bActivate) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->OpenDropDownList(bActivate); +} +FX_BOOL IFWL_ComboBox::EditCanUndo() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanUndo(); +} +FX_BOOL IFWL_ComboBox::EditCanRedo() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanRedo(); +} +FX_BOOL IFWL_ComboBox::EditUndo() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo(); +} +FX_BOOL IFWL_ComboBox::EditRedo() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo(); +} +FX_BOOL IFWL_ComboBox::EditCanCopy() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCopy(); +} +FX_BOOL IFWL_ComboBox::EditCanCut() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCut(); +} +FX_BOOL IFWL_ComboBox::EditCanSelectAll() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanSelectAll(); +} +FX_BOOL IFWL_ComboBox::EditCopy(CFX_WideString& wsCopy) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCopy(wsCopy); +} +FX_BOOL IFWL_ComboBox::EditCut(CFX_WideString& wsCut) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCut(wsCut); +} +FX_BOOL IFWL_ComboBox::EditPaste(const CFX_WideString& wsPaste) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditPaste(wsPaste); +} +FX_BOOL IFWL_ComboBox::EditSelectAll() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditSelectAll(); +} +FX_BOOL IFWL_ComboBox::EditDelete() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDelete(); +} +FX_BOOL IFWL_ComboBox::EditDeSelect() { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDeSelect(); +} +FWL_ERR IFWL_ComboBox::GetBBox(CFX_RectF& rect) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetBBox(rect); +} +FWL_ERR IFWL_ComboBox::EditModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved) { + return static_cast<CFWL_ComboBoxImp*>(GetImpl()) + ->EditModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); +} + +CFWL_ComboEditImp::CFWL_ComboEditImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_EditImp(properties, pOuter) { + m_pOuter = static_cast<CFWL_ComboBoxImp*>(pOuter->GetImpl()); +} + +CFWL_ComboEditImpDelegate::CFWL_ComboEditImpDelegate(CFWL_ComboEditImp* pOwner) + : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) {} +int32_t CFWL_ComboEditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + FX_BOOL backDefault = TRUE; + switch (dwMsgCode) { + case FWL_MSGHASH_SetFocus: + case FWL_MSGHASH_KillFocus: { + if (dwMsgCode == FWL_MSGHASH_SetFocus) { + m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + } else { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; + } + backDefault = FALSE; + break; + } + case FWL_MSGHASH_Mouse: { + CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); + if ((pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) && + ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)) { + m_pOwner->SetSelected(); + m_pOwner->SetComboBoxFocus(TRUE); + } + break; + } + default: {} + } + if (!backDefault) { + return 1; + } + return CFWL_EditImpDelegate::OnProcessMessage(pMessage); +} +void CFWL_ComboEditImp::ClearSelected() { + ClearSelections(); + Repaint(&m_rtClient); +} +void CFWL_ComboEditImp::SetSelected() { + FlagFocus(TRUE); + EndCaret(); + AddSelRange(0); +} +void CFWL_ComboEditImp::EndCaret() { + m_pEdtEngine->MoveCaretPos(MC_End); +} +void CFWL_ComboEditImp::FlagFocus(FX_BOOL bSet) { + if (bSet) { + m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + } else { + m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; + ShowCaret(FALSE); + } +} +void CFWL_ComboEditImp::SetComboBoxFocus(FX_BOOL bSet) { + m_pOuter->SetFocus(bSet); +} +CFWL_ComboListImp::CFWL_ComboListImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_ListBoxImp(properties, pOuter), m_bNotifyOwner(TRUE) { + FXSYS_assert(pOuter != NULL); +} +FWL_ERR CFWL_ComboListImp::Initialize() { + if (CFWL_ListBoxImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + delete m_pDelegate; + m_pDelegate = new CFWL_ComboListImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboListImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_ListBoxImp::Finalize(); +} +int32_t CFWL_ComboListImp::MatchItem(const CFX_WideString& wsMatch) { + if (wsMatch.IsEmpty()) { + return -1; + } + if (!m_pProperties->m_pDataProvider) + return -1; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + CFX_WideString wsText; + pData->GetItemText(m_pInterface, hItem, wsText); + FX_STRSIZE pos = wsText.Find(wsMatch.c_str()); + if (!pos) { + return i; + } + } + return -1; +} +void CFWL_ComboListImp::ChangeSelected(int32_t iSel) { + if (!m_pProperties->m_pDataProvider) + return; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel); + CFX_RectF rtInvalidate; + rtInvalidate.Reset(); + FWL_HLISTITEM hOld = GetSelItem(0); + int32_t iOld = pData->GetItemIndex(m_pInterface, hOld); + if (iOld == iSel) { + return; + } else if (iOld > -1) { + GetItemRect(iOld, rtInvalidate); + SetSelItem(hOld, FALSE); + } + if (hItem) { + CFX_RectF rect; + GetItemRect(iSel, rect); + rtInvalidate.Union(rect); + FWL_HLISTITEM hSel = pData->GetItem(m_pInterface, iSel); + SetSelItem(hSel, TRUE); + } + if (!rtInvalidate.IsEmpty()) { + Repaint(&rtInvalidate); + } +} +int32_t CFWL_ComboListImp::CountItems() { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + return pData ? pData->CountItems(m_pInterface) : 0; +} +void CFWL_ComboListImp::GetItemRect(int32_t nIndex, CFX_RectF& rtItem) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, nIndex); + pData->GetItemRect(m_pInterface, hItem, rtItem); +} +void CFWL_ComboListImp::ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy) { + fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top; + IFWL_Widget* pOwner = GetOwner(); + if (!pOwner) + return; + pOwner->TransformTo(m_pOuter, fx, fy); +} +void CFWL_ComboListImp::SetFocus(FX_BOOL bSet) { + CFWL_WidgetImp::SetFocus(bSet); +} +CFWL_ComboListImpDelegate::CFWL_ComboListImpDelegate(CFWL_ComboListImp* pOwner) + : CFWL_ListBoxImpDelegate(pOwner), m_pOwner(pOwner) {} +int32_t CFWL_ComboListImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwHashCode = pMessage->GetClassID(); + FX_BOOL backDefault = TRUE; + if (dwHashCode == FWL_MSGHASH_SetFocus || + dwHashCode == FWL_MSGHASH_KillFocus) { + OnDropListFocusChanged(pMessage, dwHashCode == FWL_MSGHASH_SetFocus); + } else if (dwHashCode == FWL_MSGHASH_Mouse) { + CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); + if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) { + CFX_RectF rect; + m_pOwner->m_pVertScrollBar->GetWidgetRect(rect); + if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { + pMsg->m_fx -= rect.left; + pMsg->m_fy -= rect.top; + IFWL_WidgetDelegate* pDelegate = + m_pOwner->m_pVertScrollBar->SetDelegate(NULL); + return pDelegate->OnProcessMessage(pMsg); + } + } + FX_DWORD dwCmd = pMsg->m_dwCmd; + switch (dwCmd) { + case FWL_MSGMOUSECMD_MouseMove: { + backDefault = FALSE; + OnDropListMouseMove(pMsg); + break; + } + case FWL_MSGMOUSECMD_LButtonDown: { + backDefault = FALSE; + OnDropListLButtonDown(pMsg); + break; + } + case FWL_MSGMOUSECMD_LButtonUp: { + backDefault = FALSE; + OnDropListLButtonUp(pMsg); + break; + } + default: {} + } + } else if (dwHashCode == FWL_MSGHASH_Key) { + backDefault = !OnDropListKey(static_cast<CFWL_MsgKey*>(pMessage)); + } + if (!backDefault) { + return 1; + } + return CFWL_ListBoxImpDelegate::OnProcessMessage(pMessage); +} +void CFWL_ComboListImpDelegate::OnDropListFocusChanged(CFWL_Message* pMsg, + FX_BOOL bSet) { + if (!bSet) { + CFWL_MsgKillFocus* pKill = static_cast<CFWL_MsgKillFocus*>(pMsg); + CFWL_ComboBoxImp* pOuter = + static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); + if (pKill->m_pSetFocus == m_pOwner->m_pOuter || + pKill->m_pSetFocus == pOuter->m_pEdit.get()) { + pOuter->ShowDropList(FALSE); + } + } +} +int32_t CFWL_ComboListImpDelegate::OnDropListMouseMove(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + if (m_pOwner->m_bNotifyOwner) { + m_pOwner->m_bNotifyOwner = FALSE; + } + if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) { + CFX_RectF rect; + m_pOwner->m_pVertScrollBar->GetWidgetRect(rect); + if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { + return 1; + } + } + FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); + if (hItem) { + if (!m_pOwner->m_pProperties->m_pDataProvider) + return 0; + IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>( + m_pOwner->m_pProperties->m_pDataProvider); + int32_t iSel = pData->GetItemIndex(m_pOwner->m_pInterface, hItem); + CFWL_EvtCmbHoverChanged event; + event.m_pSrcTarget = m_pOwner->m_pOuter; + event.m_iCurHover = iSel; + m_pOwner->DispatchEvent(&event); + m_pOwner->ChangeSelected(iSel); + } + } else if (m_pOwner->m_bNotifyOwner) { + m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy); + CFWL_ComboBoxImp* pOuter = + static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); + pOuter->m_pDelegate->OnProcessMessage(pMsg); + } + return 1; +} +int32_t CFWL_ComboListImpDelegate::OnDropListLButtonDown(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + return 0; + } + CFWL_ComboBoxImp* pOuter = + static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); + pOuter->ShowDropList(FALSE); + return 1; +} +int32_t CFWL_ComboListImpDelegate::OnDropListLButtonUp(CFWL_MsgMouse* pMsg) { + CFWL_ComboBoxImp* pOuter = + static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); + if (m_pOwner->m_bNotifyOwner) { + m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy); + pOuter->m_pDelegate->OnProcessMessage(pMsg); + } else { + if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) { + CFX_RectF rect; + m_pOwner->m_pVertScrollBar->GetWidgetRect(rect); + if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { + return 1; + } + } + pOuter->ShowDropList(FALSE); + FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); + if (hItem) { + pOuter->ProcessSelChanged(TRUE); + } + } + return 1; +} +int32_t CFWL_ComboListImpDelegate::OnDropListKey(CFWL_MsgKey* pKey) { + CFWL_ComboBoxImp* pOuter = + static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); + FX_BOOL bPropagate = FALSE; + if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) { + FX_DWORD dwKeyCode = pKey->m_dwKeyCode; + switch (dwKeyCode) { + case FWL_VKEY_Return: + case FWL_VKEY_Escape: { + pOuter->ShowDropList(FALSE); + return 1; + } + case FWL_VKEY_Up: + case FWL_VKEY_Down: { + OnDropListKeyDown(pKey); + pOuter->SetDelegate(nullptr); + pOuter->ProcessSelChanged(FALSE); + return 1; + } + default: { bPropagate = TRUE; } + } + } else if (pKey->m_dwCmd == FWL_MSGKEYCMD_Char) { + bPropagate = TRUE; + } + if (bPropagate) { + pKey->m_pDstTarget = m_pOwner->m_pOuter; + pOuter->m_pDelegate->OnProcessMessage(pKey); + return 1; + } + return 0; +} +void CFWL_ComboListImpDelegate::OnDropListKeyDown(CFWL_MsgKey* pKey) { + FX_DWORD dwKeyCode = pKey->m_dwKeyCode; + switch (dwKeyCode) { + case FWL_VKEY_Up: + case FWL_VKEY_Down: + case FWL_VKEY_Home: + case FWL_VKEY_End: { + CFWL_ComboBoxImp* pOuter = + static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); + IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>( + m_pOwner->m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = + pData->GetItem(m_pOwner->m_pInterface, pOuter->m_iCurSel); + hItem = m_pOwner->GetItem(hItem, dwKeyCode); + if (!hItem) { + break; + } + m_pOwner->SetSelection(hItem, hItem, TRUE); + m_pOwner->ScrollToVisible(hItem); + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width, + m_pOwner->m_pProperties->m_rtWidget.height); + m_pOwner->Repaint(&rtInvalidate); + break; + } + default: {} + } +} +CFWL_ComboBoxImp::CFWL_ComboBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_pForm(NULL), + m_bLButtonDown(FALSE), + m_iCurSel(-1), + m_iBtnState(FWL_PARTSTATE_CMB_Normal), + m_fComboFormHandler(0), + m_bNeedShowList(FALSE) { + m_rtClient.Reset(); + m_rtBtn.Reset(); + m_rtHandler.Reset(); +} +CFWL_ComboBoxImp::~CFWL_ComboBoxImp() {} +FWL_ERR CFWL_ComboBoxImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_ComboBox; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ComboBoxImp::GetClassID() const { + return FWL_CLASSHASH_ComboBox; +} +FWL_ERR CFWL_ComboBoxImp::Initialize() { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_Initialize(); + } + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_WGTSTATE_Invisible; // Probably a bug; not a FWL_ERR_ value. + m_pDelegate = new CFWL_ComboBoxImpDelegate(this); + CFWL_WidgetImpProperties prop; + prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; + prop.m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText) { + prop.m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon; + } + prop.m_pDataProvider = m_pProperties->m_pDataProvider; + m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface)); + m_pListBox->Initialize(); + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) { + CFWL_WidgetImpProperties prop2; + m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop2, m_pInterface)); + m_pEdit->Initialize(); + static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface); + } + if (m_pEdit) { + m_pEdit->SetParent(m_pInterface); + } + SetStates(m_pProperties->m_dwStates); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::Finalize() { + if (m_pEdit) { + m_pEdit->Finalize(); + } + m_pListBox->Finalize(); + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_ComboBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Reset(); + FX_BOOL bIsDropDown = IsDropDownStyle(); + if (bIsDropDown && m_pEdit) { + m_pEdit->GetWidgetRect(rect, TRUE); + } else { + rect.width = 100; + rect.height = 16; + } + if (!m_pProperties->m_pThemeProvider) { + ReSetTheme(); + } + FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>( + GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pFWidth) + return FWL_ERR_Indefinite; + rect.Inflate(0, 0, *pFWidth, 0); + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::ModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); + } + FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown; + FX_BOOL bRemoveDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown; + if (bAddDropDown && !m_pEdit) { + CFWL_WidgetImpProperties prop; + m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, nullptr)); + m_pEdit->Initialize(); + static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface); + m_pEdit->SetParent(m_pInterface); + } else if (bRemoveDropDown && m_pEdit) { + m_pEdit->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } + return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); +} +FWL_ERR CFWL_ComboBoxImp::Update() { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_Update(); + } + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + ReSetTheme(); + FX_BOOL bDropDown = IsDropDownStyle(); + if (bDropDown && m_pEdit) { + ReSetEditAlignment(); + } + if (m_pProperties->m_pThemeProvider == NULL) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + Layout(); + CFWL_ThemePart part; + part.m_pWidget = m_pInterface; + m_fComboFormHandler = + *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity( + &part, FWL_WGTCAPACITY_CMB_ComboFormHandler)); + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ComboBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_HitTest(fx, fy); + } + return CFWL_WidgetImp::HitTest(fx, fy); +} +FWL_ERR CFWL_ComboBoxImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_DrawWidget(pGraphics, pMatrix); + } + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + FX_BOOL bIsDropDown = IsDropDownStyle(); + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_CMB_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_CMB_Edge, pTheme, pMatrix); + } + if (!bIsDropDown) { + CFX_RectF rtTextBk(m_rtClient); + rtTextBk.width -= m_rtBtn.width; + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_CMB_Background; + param.m_pGraphics = pGraphics; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = rtTextBk; + if (m_iCurSel >= 0) { + IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>( + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->m_pProperties->m_pDataProvider); + void* p = pData->GetItemData(m_pListBox.get(), + pData->GetItem(m_pListBox.get(), m_iCurSel)); + if (p != NULL) { + param.m_pData = p; + } + } + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + param.m_dwStates = FWL_PARTSTATE_CMB_Disabled; + } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && + (m_iCurSel >= 0)) { + param.m_dwStates = FWL_PARTSTATE_CMB_Selected; + } else { + param.m_dwStates = FWL_PARTSTATE_CMB_Normal; + } + pTheme->DrawBackground(¶m); + if (m_iCurSel >= 0) { + if (!m_pListBox) + return FWL_ERR_Indefinite; + CFX_WideString wsText; + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->GetItemText(hItem, wsText); + CFWL_ThemeText param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_CMB_Caption; + param.m_dwStates = m_iBtnState; + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = rtTextBk; + param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) + ? FWL_PARTSTATE_CMB_Selected + : FWL_PARTSTATE_CMB_Normal; + param.m_wsText = wsText; + param.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + param.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + pTheme->DrawText(¶m); + } + } + { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_CMB_DropDownButton; + param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) + ? FWL_PARTSTATE_CMB_Disabled + : m_iBtnState; + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = m_rtBtn; + pTheme->DrawBackground(¶m); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { + if (!pThemeProvider) + return FWL_ERR_Indefinite; + m_pProperties->m_pThemeProvider = pThemeProvider; + if (m_pListBox && pThemeProvider->IsValidWidget(m_pListBox.get())) { + m_pListBox->SetThemeProvider(pThemeProvider); + } + if (m_pEdit && pThemeProvider->IsValidWidget(m_pEdit.get())) { + m_pEdit->SetThemeProvider(pThemeProvider); + } + return FWL_ERR_Succeeded; +} +int32_t CFWL_ComboBoxImp::GetCurSel() { + return m_iCurSel; +} +FWL_ERR CFWL_ComboBoxImp::SetCurSel(int32_t iSel) { + int32_t iCount = + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->CountItems(); + FX_BOOL bClearSel = iSel < 0 || iSel >= iCount; + FX_BOOL bDropDown = IsDropDownStyle(); + if (bDropDown && m_pEdit) { + if (bClearSel) { + m_pEdit->SetText(CFX_WideString()); + } else { + CFX_WideString wsText; + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel); + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->GetItemText(hItem, wsText); + m_pEdit->SetText(wsText); + } + m_pEdit->Update(); + } + m_iCurSel = bClearSel ? -1 : iSel; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) { + FX_BOOL bIsDropDown = IsDropDownStyle(); + if (bIsDropDown && m_pEdit) { + m_pEdit->SetStates(dwStates, bSet); + } + if (m_pListBox) { + m_pListBox->SetStates(dwStates, bSet); + } + return CFWL_WidgetImp::SetStates(dwStates, bSet); +} +FWL_ERR CFWL_ComboBoxImp::SetEditText(const CFX_WideString& wsText) { + if (!m_pEdit) + return FWL_ERR_Indefinite; + m_pEdit->SetText(wsText); + return m_pEdit->Update(); +} +int32_t CFWL_ComboBoxImp::GetEditTextLength() const { + if (!m_pEdit) + return -1; + return m_pEdit->GetTextLength(); +} +FWL_ERR CFWL_ComboBoxImp::GetEditText(CFX_WideString& wsText, + int32_t nStart, + int32_t nCount) const { + if (m_pEdit) { + return m_pEdit->GetText(wsText, nStart, nCount); + } else if (m_pListBox) { + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); + return m_pListBox->GetItemText(hItem, wsText); + } + return FWL_ERR_Indefinite; +} +FWL_ERR CFWL_ComboBoxImp::SetEditSelRange(int32_t nStart, int32_t nCount) { + if (!m_pEdit) + return FWL_ERR_Indefinite; + static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->ClearSelected(); + m_pEdit->AddSelRange(nStart, nCount); + return FWL_ERR_Succeeded; +} +int32_t CFWL_ComboBoxImp::GetEditSelRange(int32_t nIndex, int32_t& nStart) { + if (!m_pEdit) + return -1; + return m_pEdit->GetSelRange(nIndex, nStart); +} +int32_t CFWL_ComboBoxImp::GetEditLimit() { + if (!m_pEdit) + return -1; + return m_pEdit->GetLimit(); +} +FWL_ERR CFWL_ComboBoxImp::SetEditLimit(int32_t nLimit) { + if (!m_pEdit) + return FWL_ERR_Indefinite; + return m_pEdit->SetLimit(nLimit); +} +FWL_ERR CFWL_ComboBoxImp::EditDoClipboard(int32_t iCmd) { + if (!m_pEdit) + return FWL_ERR_Indefinite; + return m_pEdit->DoClipboard(iCmd); +} +FX_BOOL CFWL_ComboBoxImp::EditRedo(const CFX_ByteStringC& bsRecord) { + if (!m_pEdit) + return FALSE; + return m_pEdit->Redo(bsRecord); +} +FX_BOOL CFWL_ComboBoxImp::EditUndo(const CFX_ByteStringC& bsRecord) { + if (!m_pEdit) + return FALSE; + return m_pEdit->Undo(bsRecord); +} +IFWL_ListBox* CFWL_ComboBoxImp::GetListBoxt() { + return m_pListBox.get(); +} +FX_BOOL CFWL_ComboBoxImp::AfterFocusShowDropList() { + if (!m_bNeedShowList) { + return FALSE; + } + if (m_pEdit) { + MatchEditText(); + } + ShowDropList(TRUE); + m_bNeedShowList = FALSE; + return TRUE; +} +FX_ERR CFWL_ComboBoxImp::OpenDropDownList(FX_BOOL bActivate) { + ShowDropList(bActivate); + return FWL_ERR_Succeeded; +} +FX_BOOL CFWL_ComboBoxImp::EditCanUndo() { + return m_pEdit->CanUndo(); +} +FX_BOOL CFWL_ComboBoxImp::EditCanRedo() { + return m_pEdit->CanRedo(); +} +FX_BOOL CFWL_ComboBoxImp::EditUndo() { + return m_pEdit->Undo(); +} +FX_BOOL CFWL_ComboBoxImp::EditRedo() { + return m_pEdit->Redo(); +} +FX_BOOL CFWL_ComboBoxImp::EditCanCopy() { + return m_pEdit->CountSelRanges() > 0; +} +FX_BOOL CFWL_ComboBoxImp::EditCanCut() { + if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) { + return FALSE; + } + return m_pEdit->CountSelRanges() > 0; +} +FX_BOOL CFWL_ComboBoxImp::EditCanSelectAll() { + return m_pEdit->GetTextLength() > 0; +} +FX_BOOL CFWL_ComboBoxImp::EditCopy(CFX_WideString& wsCopy) { + return m_pEdit->Copy(wsCopy); +} +FX_BOOL CFWL_ComboBoxImp::EditCut(CFX_WideString& wsCut) { + return m_pEdit->Cut(wsCut); +} +FX_BOOL CFWL_ComboBoxImp::EditPaste(const CFX_WideString& wsPaste) { + return m_pEdit->Paste(wsPaste); +} +FX_BOOL CFWL_ComboBoxImp::EditSelectAll() { + return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded; +} +FX_BOOL CFWL_ComboBoxImp::EditDelete() { + return m_pEdit->ClearText() == FWL_ERR_Succeeded; +} +FX_BOOL CFWL_ComboBoxImp::EditDeSelect() { + return m_pEdit->ClearSelections() == FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::GetBBox(CFX_RectF& rect) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_GetBBox(rect); + } + rect = m_pProperties->m_rtWidget; + if (m_pListBox && IsDropListShowed()) { + CFX_RectF rtList; + m_pListBox->GetWidgetRect(rtList); + rtList.Offset(rect.left, rect.top); + rect.Union(rtList); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::EditModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved) { + if (m_pEdit != NULL) { + return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); + } else { + return FWL_ERR_Parameter_Invalid; + } +} +FX_FLOAT CFWL_ComboBoxImp::GetListHeight() { + return static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider) + ->GetListHeight(m_pInterface); +} +void CFWL_ComboBoxImp::DrawStretchHandler(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground param; + param.m_pGraphics = pGraphics; + param.m_iPart = FWL_PART_CMB_StretcgHandler; + param.m_dwStates = FWL_PARTSTATE_CMB_Normal; + param.m_pWidget = m_pInterface; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = m_rtHandler; + m_pProperties->m_pThemeProvider->DrawBackground(¶m); +} +void CFWL_ComboBoxImp::ShowDropList(FX_BOOL bActivate) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_ShowDropList(bActivate); + } + FX_BOOL bDropList = IsDropListShowed(); + if (bDropList == bActivate) { + return; + } + if (!m_pForm) { + InitProxyForm(); + } + m_pListProxyDelegate->Reset(); + if (bActivate) { + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->ChangeSelected(m_iCurSel); + ReSetListItemAlignment(); + FX_DWORD dwStyleAdd = m_pProperties->m_dwStyleExes & + (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw); + m_pListBox->ModifyStylesEx(dwStyleAdd, 0); + m_pListBox->GetWidgetRect(m_rtList, TRUE); + FX_FLOAT fHeight = GetListHeight(); + if (fHeight > 0) { + if (m_rtList.height > GetListHeight()) { + m_rtList.height = GetListHeight(); + m_pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll, 0); + } + } + CFX_RectF rtAnchor; + rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width, + m_pProperties->m_rtWidget.height); + FX_FLOAT fMinHeight = 0; + if (m_rtList.width < m_rtClient.width) { + m_rtList.width = m_rtClient.width; + } + m_rtProxy = m_rtList; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) { + m_rtProxy.height += m_fComboFormHandler; + } + GetPopupPos(fMinHeight, m_rtProxy.height, rtAnchor, m_rtProxy); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) { + FX_FLOAT fx = 0; + FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2; + TransformTo(NULL, fx, fy); + m_bUpFormHandler = fy > m_rtProxy.top; + if (m_bUpFormHandler) { + m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler); + m_rtList.top = m_fComboFormHandler; + } else { + m_rtHandler.Set(0, m_rtList.height, m_rtList.width, + m_fComboFormHandler); + } + } + m_pForm->SetWidgetRect(m_rtProxy); + m_pForm->Update(); + m_pListBox->SetWidgetRect(m_rtList); + m_pListBox->Update(); + CFWL_EvtCmbPreDropDown ev; + ev.m_pSrcTarget = m_pInterface; + DispatchEvent(&ev); + m_fItemHeight = + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_fItemHeight; + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(TRUE); + m_pForm->DoModal(); + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(FALSE); + } else { + m_pForm->EndDoModal(); + CFWL_EvtCmbCloseUp ev; + ev.m_pSrcTarget = m_pInterface; + DispatchEvent(&ev); + m_bLButtonDown = FALSE; + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_bNotifyOwner = + TRUE; + SetFocus(TRUE); + } +} +FX_BOOL CFWL_ComboBoxImp::IsDropListShowed() { + return m_pForm && !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible); +} +FX_BOOL CFWL_ComboBoxImp::IsDropDownStyle() const { + return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown; +} +void CFWL_ComboBoxImp::MatchEditText() { + CFX_WideString wsText; + m_pEdit->GetText(wsText); + int32_t iMatch = + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->MatchItem(wsText); + if (iMatch != m_iCurSel) { + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->ChangeSelected(iMatch); + if (iMatch >= 0) { + SynchrEditText(iMatch); + } + } else if (iMatch >= 0) { + static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected(); + } + m_iCurSel = iMatch; +} +void CFWL_ComboBoxImp::SynchrEditText(int32_t iListItem) { + CFX_WideString wsText; + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iListItem); + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->GetItemText(hItem, wsText); + m_pEdit->SetText(wsText); + m_pEdit->Update(); + static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected(); +} +void CFWL_ComboBoxImp::Layout() { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_Layout(); + } + GetClientRect(m_rtClient); + FX_FLOAT* pFWidth = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pFWidth) + return; + FX_FLOAT fBtn = *pFWidth; + m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn, + m_rtClient.height); + FX_BOOL bIsDropDown = IsDropDownStyle(); + if (bIsDropDown && m_pEdit) { + CFX_RectF rtEdit; + rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn, + m_rtClient.height); + m_pEdit->SetWidgetRect(rtEdit); + if (m_iCurSel >= 0) { + CFX_WideString wsText; + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->GetItemText(hItem, wsText); + m_pEdit->LockUpdate(); + m_pEdit->SetText(wsText); + m_pEdit->UnlockUpdate(); + } + m_pEdit->Update(); + } +} +void CFWL_ComboBoxImp::ReSetTheme() { + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (!pTheme) { + pTheme = GetAvailableTheme(); + m_pProperties->m_pThemeProvider = pTheme; + } + if (m_pListBox) { + if (!m_pListBox->GetThemeProvider() && + pTheme->IsValidWidget(m_pListBox.get())) { + m_pListBox->SetThemeProvider(pTheme); + } + } + if (m_pEdit) { + if (!m_pEdit->GetThemeProvider() && pTheme->IsValidWidget(m_pEdit.get())) { + m_pEdit->SetThemeProvider(pTheme); + } + } +} +void CFWL_ComboBoxImp::ReSetEditAlignment() { + if (!m_pEdit) + return; + FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes; + FX_DWORD dwAdd = 0; + switch (dwStylExes & FWL_STYLEEXT_CMB_EditHAlignMask) { + case FWL_STYLEEXT_CMB_EditHCenter: { + dwAdd |= FWL_STYLEEXT_EDT_HCenter; + break; + } + case FWL_STYLEEXT_CMB_EditHFar: { + dwAdd |= FWL_STYLEEXT_EDT_HFar; + break; + } + default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; } + } + switch (dwStylExes & FWL_STYLEEXT_CMB_EditVAlignMask) { + case FWL_STYLEEXT_CMB_EditVCenter: { + dwAdd |= FWL_STYLEEXT_EDT_VCenter; + break; + } + case FWL_STYLEEXT_CMB_EditVFar: { + dwAdd |= FWL_STYLEEXT_EDT_VFar; + break; + } + default: { dwAdd |= FWL_STYLEEXT_EDT_VNear; } + } + if (dwStylExes & FWL_STYLEEXT_CMB_EditJustified) { + dwAdd |= FWL_STYLEEXT_EDT_Justified; + } + if (dwStylExes & FWL_STYLEEXT_CMB_EditDistributed) { + dwAdd |= FWL_STYLEEXT_EDT_Distributed; + } + m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask | + FWL_STYLEEXT_EDT_HAlignModeMask | + FWL_STYLEEXT_EDT_VAlignMask); +} +void CFWL_ComboBoxImp::ReSetListItemAlignment() { + if (!m_pListBox) + return; + FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes; + FX_DWORD dwAdd = 0; + switch (dwStylExes & FWL_STYLEEXT_CMB_ListItemAlignMask) { + case FWL_STYLEEXT_CMB_ListItemCenterAlign: { + dwAdd |= FWL_STYLEEXT_LTB_CenterAlign; + } + case FWL_STYLEEXT_CMB_ListItemRightAlign: { + dwAdd |= FWL_STYLEEXT_LTB_RightAlign; + } + default: { dwAdd |= FWL_STYLEEXT_LTB_LeftAlign; } + } + m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask); +} +void CFWL_ComboBoxImp::ProcessSelChanged(FX_BOOL bLButtonUp) { + IFWL_ComboBoxDP* pDatas = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + m_iCurSel = pDatas->GetItemIndex(m_pInterface, m_pListBox->GetSelItem(0)); + FX_BOOL bDropDown = IsDropDownStyle(); + if (bDropDown) { + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); + if (hItem) { + CFX_WideString wsText; + pData->GetItemText(m_pInterface, hItem, wsText); + if (m_pEdit) { + m_pEdit->SetText(wsText); + m_pEdit->Update(); + static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected(); + } + CFWL_EvtCmbSelChanged ev; + ev.bLButtonUp = bLButtonUp; + ev.m_pSrcTarget = m_pInterface; + ev.iArraySels.Add(m_iCurSel); + DispatchEvent(&ev); + } + } else { + Repaint(&m_rtClient); + } +} +void CFWL_ComboBoxImp::InitProxyForm() { + if (m_pForm) + return; + if (!m_pListBox) + return; + CFWL_WidgetImpProperties propForm; + propForm.m_pOwner = m_pInterface; + propForm.m_dwStyles = FWL_WGTSTYLE_Popup; + propForm.m_dwStates = FWL_WGTSTATE_Invisible; + CFX_WideString className; + m_pForm = IFWL_Form::CreateFormProxy(propForm, &className, m_pListBox.get()); + m_pForm->Initialize(); + m_pProxy = static_cast<CFWL_FormProxyImp*>(m_pForm->GetImpl()); + m_pListBox->SetParent(m_pForm); + m_pListProxyDelegate = new CFWL_ComboProxyImpDelegate(m_pForm, this); + m_pProxy->SetDelegate(m_pListProxyDelegate); +} +FWL_ERR CFWL_ComboBoxImp::DisForm_Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_WGTSTATE_Invisible; // Ditto. + m_pDelegate = new CFWL_ComboBoxImpDelegate(this); + DisForm_InitComboList(); + DisForm_InitComboEdit(); + return FWL_ERR_Succeeded; +} +void CFWL_ComboBoxImp::DisForm_InitComboList() { + if (m_pListBox) { + return; + } + CFWL_WidgetImpProperties prop; + prop.m_pParent = m_pInterface; + prop.m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; + prop.m_dwStates = FWL_WGTSTATE_Invisible; + prop.m_pDataProvider = m_pProperties->m_pDataProvider; + prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; + m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface)); + m_pListBox->Initialize(); +} +void CFWL_ComboBoxImp::DisForm_InitComboEdit() { + if (m_pEdit) { + return; + } + CFWL_WidgetImpProperties prop; + prop.m_pParent = m_pInterface; + prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; + m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, m_pInterface)); + m_pEdit->Initialize(); + static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface); +} +void CFWL_ComboBoxImp::DisForm_ShowDropList(FX_BOOL bActivate) { + FX_BOOL bDropList = DisForm_IsDropListShowed(); + if (bDropList == bActivate) { + return; + } + if (bActivate) { + CFWL_EvtCmbPreDropDown preEvent; + preEvent.m_pSrcTarget = m_pInterface; + DispatchEvent(&preEvent); + CFWL_ComboListImp* pComboList = + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()); + int32_t iItems = pComboList->CountItems(); + if (iItems < 1) { + return; + } + ReSetListItemAlignment(); + pComboList->ChangeSelected(m_iCurSel); + FX_FLOAT fItemHeight = pComboList->GetItemHeigt(); + FX_FLOAT fBorder = GetBorderSize(); + FX_FLOAT fPopupMin = 0.0f; + if (iItems > 3) { + fPopupMin = fItemHeight * 3 + fBorder * 2; + } + FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2; + CFX_RectF rtList; + rtList.left = m_rtClient.left; + rtList.width = m_pProperties->m_rtWidget.width; + rtList.top = 0; + rtList.height = 0; + GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList); + m_pListBox->SetWidgetRect(rtList); + m_pListBox->Update(); + } else { + SetFocus(TRUE); + } + m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate); + if (bActivate) { + CFWL_EvtCmbPostDropDown postEvent; + postEvent.m_pSrcTarget = m_pInterface; + DispatchEvent(&postEvent); + } + CFX_RectF rect; + m_pListBox->GetWidgetRect(rect); + rect.Inflate(2, 2); + Repaint(&rect); +} +FX_BOOL CFWL_ComboBoxImp::DisForm_IsDropListShowed() { + return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible); +} +FWL_ERR CFWL_ComboBoxImp::DisForm_ModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved) { + if (!m_pEdit) { + DisForm_InitComboEdit(); + } + FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown; + FX_BOOL bDelDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown; + dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown; + m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown; + if (bAddDropDown) { + m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly); + } else if (bDelDropDown) { + m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0); + } + return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); +} +FWL_ERR CFWL_ComboBoxImp::DisForm_Update() { + if (m_iLock) { + return FWL_ERR_Indefinite; + } + if (m_pEdit) { + ReSetEditAlignment(); + } + ReSetTheme(); + Layout(); + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ComboBoxImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) { + CFX_RectF rect; + rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width, + m_pProperties->m_rtWidget.height); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_Edit; + } + if (m_rtBtn.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + if (DisForm_IsDropListShowed()) { + m_pListBox->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + } + return FWL_WGTHITTEST_Unknown; +} +FWL_ERR CFWL_ComboBoxImp::DisForm_DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + CFX_Matrix mtOrg; + mtOrg.Set(1, 0, 0, 1, 0, 0); + if (pMatrix) { + mtOrg = *pMatrix; + } + FX_BOOL bListShowed = m_pListBox && DisForm_IsDropListShowed(); + pGraphics->SaveGraphState(); + pGraphics->ConcatMatrix(&mtOrg); + if (!m_rtBtn.IsEmpty(0.1f)) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_CMB_DropDownButton; + param.m_dwStates = m_iBtnState; + param.m_pGraphics = pGraphics; + param.m_rtPart = m_rtBtn; + pTheme->DrawBackground(¶m); + } + pGraphics->RestoreGraphState(); + if (m_pEdit) { + CFX_RectF rtEdit; + m_pEdit->GetWidgetRect(rtEdit); + CFX_Matrix mt; + mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top); + mt.Concat(mtOrg); + m_pEdit->DrawWidget(pGraphics, &mt); + } + if (bListShowed) { + CFX_RectF rtList; + m_pListBox->GetWidgetRect(rtList); + CFX_Matrix mt; + mt.Set(1, 0, 0, 1, rtList.left, rtList.top); + mt.Concat(mtOrg); + m_pListBox->DrawWidget(pGraphics, &mt); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImp::DisForm_GetBBox(CFX_RectF& rect) { + rect = m_pProperties->m_rtWidget; + if (m_pListBox && DisForm_IsDropListShowed()) { + CFX_RectF rtList; + m_pListBox->GetWidgetRect(rtList); + rtList.Offset(rect.left, rect.top); + rect.Union(rtList); + } + return FWL_ERR_Succeeded; +} +void CFWL_ComboBoxImp::DisForm_Layout() { + GetClientRect(m_rtClient); + m_rtContent = m_rtClient; + FX_FLOAT* pFWidth = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pFWidth) + return; + FX_FLOAT borderWidth = 0; + { borderWidth = FWL_PART_CMB_Border; } + FX_FLOAT fBtn = *pFWidth; + if (!(GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) { + m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth, + fBtn - borderWidth, m_rtClient.height - 2 * borderWidth); + } + CFX_RectF* pUIMargin = + static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin)); + if (pUIMargin) { + m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, + pUIMargin->height); + } + FX_BOOL bIsDropDown = IsDropDownStyle(); + if (bIsDropDown && m_pEdit) { + CFX_RectF rtEdit; + rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn, + m_rtContent.height); + m_pEdit->SetWidgetRect(rtEdit); + if (m_iCurSel >= 0) { + CFX_WideString wsText; + IFWL_ComboBoxDP* pData = + static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); + static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) + ->GetItemText(hItem, wsText); + m_pEdit->LockUpdate(); + m_pEdit->SetText(wsText); + m_pEdit->UnlockUpdate(); + } + m_pEdit->Update(); + } +} +CFWL_ComboBoxImpDelegate::CFWL_ComboBoxImpDelegate(CFWL_ComboBoxImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_ComboBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) { + return DisForm_OnProcessMessage(pMessage); + } + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + FX_BOOL iRet = 1; + 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: { + OnKey(static_cast<CFWL_MsgKey*>(pMessage)); + break; + } + default: { iRet = 0; } + } + CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); + return iRet; +} +FWL_ERR CFWL_ComboBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + FX_DWORD dwFlag = pEvent->GetClassID(); + if (dwFlag == FWL_EVTHASH_LTB_DrawItem) { + CFWL_EvtLtbDrawItem* pDrawItemEvent = + static_cast<CFWL_EvtLtbDrawItem*>(pEvent); + CFWL_EvtCmbDrawItem pTemp; + pTemp.m_pSrcTarget = m_pOwner->m_pInterface; + pTemp.m_pGraphics = pDrawItemEvent->m_pGraphics; + pTemp.m_index = pDrawItemEvent->m_index; + pTemp.m_rtItem = pDrawItemEvent->m_rect; + m_pOwner->DispatchEvent(&pTemp); + } else if (dwFlag == FWL_EVTHASH_Scroll) { + CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); + CFWL_EvtScroll pScrollEv; + pScrollEv.m_pSrcTarget = m_pOwner->m_pInterface; + pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode; + pScrollEv.m_fPos = pScrollEvent->m_fPos; + m_pOwner->DispatchEvent(&pScrollEv); + } else if (dwFlag == FWL_EVTHASH_EDT_TextChanged) { + CFWL_EvtEdtTextChanged* pTextChangedEvent = + static_cast<CFWL_EvtEdtTextChanged*>(pEvent); + CFWL_EvtCmbEditChanged pTemp; + pTemp.m_pSrcTarget = m_pOwner->m_pInterface; + pTemp.wsInsert = pTextChangedEvent->wsInsert; + pTemp.wsDelete = pTextChangedEvent->wsDelete; + pTemp.nChangeType = pTextChangedEvent->nChangeType; + m_pOwner->DispatchEvent(&pTemp); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ComboBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_ComboBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg, + FX_BOOL bSet) { + IFWL_Target* pDstTarget = pMsg->m_pDstTarget; + IFWL_Target* pSrcTarget = pMsg->m_pSrcTarget; + FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); + if (bSet) { + m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + if (bDropDown && pSrcTarget != m_pOwner->m_pListBox.get()) { + if (!m_pOwner->m_pEdit) + return; + static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl()) + ->SetSelected(); + } else { + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + } else { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; + if (bDropDown && pDstTarget != m_pOwner->m_pListBox.get()) { + if (!m_pOwner->m_pEdit) + return; + static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl()) + ->FlagFocus(FALSE); + static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl()) + ->ClearSelected(); + } else { + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + } +} +void CFWL_ComboBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + return; + } + FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); + CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient; + FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy); + if (bClickBtn) { + if (bDropDown && m_pOwner->m_pEdit) { + m_pOwner->MatchEditText(); + } + m_pOwner->m_bLButtonDown = TRUE; + m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Pressed; + m_pOwner->Repaint(&m_pOwner->m_rtClient); + m_pOwner->ShowDropList(TRUE); + m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } +} +void CFWL_ComboBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + m_pOwner->m_bLButtonDown = FALSE; + if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Hovered; + } else { + m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; + } + m_pOwner->Repaint(&m_pOwner->m_rtBtn); +} +void CFWL_ComboBoxImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + int32_t iOldState = m_pOwner->m_iBtnState; + if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iBtnState = m_pOwner->m_bLButtonDown + ? FWL_PARTSTATE_CMB_Pressed + : FWL_PARTSTATE_CMB_Hovered; + } else { + m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; + } + if ((iOldState != m_pOwner->m_iBtnState) && + !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == + FWL_WGTSTATE_Disabled)) { + m_pOwner->Repaint(&m_pOwner->m_rtBtn); + } +} +void CFWL_ComboBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { + if (!m_pOwner->IsDropListShowed() && + !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == + FWL_WGTSTATE_Disabled)) { + m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; + m_pOwner->Repaint(&m_pOwner->m_rtBtn); + } +} +void CFWL_ComboBoxImpDelegate::OnKey(CFWL_MsgKey* pMsg) { + FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; + if (dwKeyCode == FWL_VKEY_Tab) { + m_pOwner->DispatchKeyEvent(pMsg); + return; + } + if (pMsg->m_pDstTarget == m_pOwner->m_pInterface) + DoSubCtrlKey(pMsg); +} +void CFWL_ComboBoxImpDelegate::DoSubCtrlKey(CFWL_MsgKey* pMsg) { + FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; + const bool bUp = dwKeyCode == FWL_VKEY_Up; + const bool bDown = dwKeyCode == FWL_VKEY_Down; + if (bUp || bDown) { + int32_t iCount = + static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()) + ->CountItems(); + if (iCount < 1) { + return; + } + FX_BOOL bMatchEqual = FALSE; + int32_t iCurSel = m_pOwner->m_iCurSel; + FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); + if (bDropDown && m_pOwner->m_pEdit) { + CFX_WideString wsText; + m_pOwner->m_pEdit->GetText(wsText); + iCurSel = static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()) + ->MatchItem(wsText); + if (iCurSel >= 0) { + CFX_WideString wsTemp; + IFWL_ComboBoxDP* pData = static_cast<IFWL_ComboBoxDP*>( + m_pOwner->m_pProperties->m_pDataProvider); + FWL_HLISTITEM hItem = pData->GetItem(m_pOwner->m_pInterface, iCurSel); + static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()) + ->GetItemText(hItem, wsTemp); + bMatchEqual = wsText.Equal(wsTemp); + } + } + if (iCurSel < 0) { + iCurSel = 0; + } else if (!bDropDown || bMatchEqual) { + if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) { + return; + } + if (bUp) { + iCurSel--; + } else { + iCurSel++; + } + } + m_pOwner->m_iCurSel = iCurSel; + if (bDropDown && m_pOwner->m_pEdit) { + m_pOwner->SynchrEditText(m_pOwner->m_iCurSel); + } else { + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + return; + } + FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); + if (bDropDown) { + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMsg); + } +} +int32_t CFWL_ComboBoxImpDelegate::DisForm_OnProcessMessage( + CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + FX_BOOL backDefault = TRUE; + switch (dwMsgCode) { + case FWL_MSGHASH_SetFocus: + case FWL_MSGHASH_KillFocus: { + backDefault = FALSE; + DisForm_OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus); + break; + } + case FWL_MSGHASH_Mouse: { + backDefault = FALSE; + CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); + FX_DWORD dwCmd = pMsg->m_dwCmd; + switch (dwCmd) { + case FWL_MSGMOUSECMD_LButtonDown: { + DisForm_OnLButtonDown(pMsg); + break; + } + case FWL_MSGMOUSECMD_LButtonUp: { + OnLButtonUp(pMsg); + break; + } + default: {} + } + break; + } + case FWL_MSGHASH_Key: { + backDefault = FALSE; + CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); + if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyUp) { + break; + } + if (m_pOwner->DisForm_IsDropListShowed() && + pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) { + FX_DWORD dwKeyCode = pKey->m_dwKeyCode; + FX_BOOL bListKey = + dwKeyCode == FWL_VKEY_Up || dwKeyCode == FWL_VKEY_Down || + dwKeyCode == FWL_VKEY_Return || dwKeyCode == FWL_VKEY_Escape; + if (bListKey) { + IFWL_WidgetDelegate* pDelegate = + m_pOwner->m_pListBox->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMessage); + break; + } + } + DisForm_OnKey(pKey); + break; + } + default: {} + } + if (!backDefault) { + return 1; + } + return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); +} +void CFWL_ComboBoxImpDelegate::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) { + FX_BOOL bDropDown = m_pOwner->DisForm_IsDropListShowed(); + CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient; + FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy); + if (bClickBtn) { + if (m_pOwner->DisForm_IsDropListShowed()) { + m_pOwner->DisForm_ShowDropList(FALSE); + return; + } + { + if (m_pOwner->m_pEdit) { + m_pOwner->MatchEditText(); + } + m_pOwner->DisForm_ShowDropList(TRUE); + } + } +} +void CFWL_ComboBoxImpDelegate::DisForm_OnFocusChanged(CFWL_Message* pMsg, + FX_BOOL bSet) { + if (bSet) { + m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + if ((m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) { + CFWL_MsgSetFocus msg; + msg.m_pDstTarget = m_pOwner->m_pEdit.get(); + msg.m_pSrcTarget = NULL; + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(&msg); + } + } else { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; + m_pOwner->DisForm_ShowDropList(FALSE); + CFWL_MsgKillFocus msg; + msg.m_pDstTarget = NULL; + msg.m_pSrcTarget = m_pOwner->m_pEdit.get(); + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(&msg); + } +} +void CFWL_ComboBoxImpDelegate::DisForm_OnKey(CFWL_MsgKey* pMsg) { + FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; + const bool bUp = dwKeyCode == FWL_VKEY_Up; + const bool bDown = dwKeyCode == FWL_VKEY_Down; + if (bUp || bDown) { + CFWL_ComboListImp* pComboList = + static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()); + int32_t iCount = pComboList->CountItems(); + if (iCount < 1) { + return; + } + FX_BOOL bMatchEqual = FALSE; + int32_t iCurSel = m_pOwner->m_iCurSel; + if (m_pOwner->m_pEdit) { + CFX_WideString wsText; + m_pOwner->m_pEdit->GetText(wsText); + iCurSel = pComboList->MatchItem(wsText); + if (iCurSel >= 0) { + CFX_WideString wsTemp; + FWL_HLISTITEM item = m_pOwner->m_pListBox->GetSelItem(iCurSel); + m_pOwner->m_pListBox->GetItemText(item, wsTemp); + bMatchEqual = wsText.Equal(wsTemp); + } + } + if (iCurSel < 0) { + iCurSel = 0; + } else if (bMatchEqual) { + if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) { + return; + } + if (bUp) { + iCurSel--; + } else { + iCurSel++; + } + } + m_pOwner->m_iCurSel = iCurSel; + m_pOwner->SynchrEditText(m_pOwner->m_iCurSel); + return; + } + if (m_pOwner->m_pEdit) { + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMsg); + } +} +CFWL_ComboProxyImpDelegate::CFWL_ComboProxyImpDelegate( + IFWL_Form* pForm, + CFWL_ComboBoxImp* pComboBox) + : m_bLButtonDown(FALSE), + m_bLButtonUpSelf(FALSE), + m_fStartPos(0), + m_pForm(pForm), + m_pComboBox(pComboBox) {} +int32_t CFWL_ComboProxyImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + if (dwMsgCode == 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; + } + default: {} + } + } + if (dwMsgCode == FWL_MSGHASH_Deactivate) { + OnDeactive(static_cast<CFWL_MsgDeactivate*>(pMessage)); + } + if (dwMsgCode == FWL_MSGHASH_KillFocus || dwMsgCode == FWL_MSGHASH_SetFocus) { + OnFocusChanged(static_cast<CFWL_MsgKillFocus*>(pMessage), + dwMsgCode == FWL_MSGHASH_SetFocus); + } + return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); +} +FWL_ERR CFWL_ComboProxyImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + m_pComboBox->DrawStretchHandler(pGraphics, pMatrix); + return FWL_ERR_Succeeded; +} +void CFWL_ComboProxyImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + IFWL_NoteThread* pThread = m_pForm->GetOwnerThread(); + if (!pThread) + return; + CFWL_NoteDriver* pDriver = + static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver()); + CFX_RectF rtWidget; + m_pForm->GetWidgetRect(rtWidget); + rtWidget.left = rtWidget.top = 0; + if (rtWidget.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_bLButtonDown = TRUE; + pDriver->SetGrab(m_pForm, TRUE); + } else { + m_bLButtonDown = FALSE; + pDriver->SetGrab(m_pForm, FALSE); + m_pComboBox->ShowDropList(FALSE); + } +} +void CFWL_ComboProxyImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + m_bLButtonDown = FALSE; + IFWL_NoteThread* pThread = m_pForm->GetOwnerThread(); + if (!pThread) + return; + CFWL_NoteDriver* pDriver = + static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver()); + pDriver->SetGrab(m_pForm, FALSE); + if (m_bLButtonUpSelf) { + CFX_RectF rect; + m_pForm->GetWidgetRect(rect); + rect.left = rect.top = 0; + if (!rect.Contains(pMsg->m_fx, pMsg->m_fy) && + m_pComboBox->IsDropListShowed()) { + m_pComboBox->ShowDropList(FALSE); + } + } else { + m_bLButtonUpSelf = TRUE; + } +} +void CFWL_ComboProxyImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {} +void CFWL_ComboProxyImpDelegate::OnDeactive(CFWL_MsgDeactivate* pMsg) { + m_pComboBox->ShowDropList(FALSE); +} +void CFWL_ComboProxyImpDelegate::OnFocusChanged(CFWL_MsgKillFocus* pMsg, + FX_BOOL bSet) { + if (!bSet) { + if (pMsg->m_pSetFocus == NULL) { + m_pComboBox->ShowDropList(FALSE); + } + } +} diff --git a/xfa/src/fwl/basewidget/fwl_comboboximp.h b/xfa/src/fwl/basewidget/fwl_comboboximp.h new file mode 100644 index 0000000000..000e0afe9c --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_comboboximp.h @@ -0,0 +1,237 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_COMBOBOXIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_COMBOBOXIMP_H_ + +#include <memory> + +#include "xfa/src/fwl/basewidget/fwl_editimp.h" +#include "xfa/src/fwl/basewidget/fwl_listboximp.h" + +class CFWL_WidgetImp; +class CFWL_WidgetImpProperties; +class CFWL_WidgetImpDelegate; +class CFWL_ListBoxImp; +class CFWL_ListBoxImpDelegate; +class CFWL_FormProxyImp; +class IFWL_Widget; +class CFWL_ComboEditImp; +class CFWL_ComboEditImpDelegate; +class CFWL_ComboListImp; +class CFWL_ComboListImpDelegate; +class CFWL_ComboBoxImp; +class CFWL_ComboBoxImpDelegate; +class CFWL_ComboProxyImpDelegate; +class CFWL_ComboEditImp : public CFWL_EditImp { + public: + CFWL_ComboEditImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + + void ClearSelected(); + void SetSelected(); + void EndCaret(); + void FlagFocus(FX_BOOL bSet); + + protected: + void SetComboBoxFocus(FX_BOOL bSet); + CFWL_ComboBoxImp* m_pOuter; + friend class CFWL_ComboEditImpDelegate; +}; +class CFWL_ComboEditImpDelegate : public CFWL_EditImpDelegate { + public: + CFWL_ComboEditImpDelegate(CFWL_ComboEditImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + + protected: + CFWL_ComboEditImp* m_pOwner; +}; +class CFWL_ComboListImp : public CFWL_ListBoxImp { + public: + CFWL_ComboListImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + int32_t MatchItem(const CFX_WideString& wsMatch); + void ChangeSelected(int32_t iSel); + int32_t CountItems(); + void GetItemRect(int32_t nIndex, CFX_RectF& rtItem); + void ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy); + void SetFocus(FX_BOOL bSet); + FX_BOOL m_bNotifyOwner; + friend class CFWL_ComboListImpDelegate; + friend class CFWL_ComboBoxImp; +}; +class CFWL_ComboListImpDelegate : public CFWL_ListBoxImpDelegate { + public: + CFWL_ComboListImpDelegate(CFWL_ComboListImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + + protected: + void OnDropListFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + int32_t OnDropListMouseMove(CFWL_MsgMouse* pMsg); + int32_t OnDropListLButtonDown(CFWL_MsgMouse* pMsg); + int32_t OnDropListLButtonUp(CFWL_MsgMouse* pMsg); + int32_t OnDropListKey(CFWL_MsgKey* pKey); + void OnDropListKeyDown(CFWL_MsgKey* pKey); + CFWL_ComboListImp* m_pOwner; +}; +class CFWL_ComboBoxImp : public CFWL_WidgetImp { + public: + CFWL_ComboBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual ~CFWL_ComboBoxImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR ModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved); + virtual FWL_ERR SetStates(FX_DWORD dwStates, FX_BOOL bSet = TRUE); + virtual FWL_ERR Update(); + virtual FX_DWORD HitTest(FX_FLOAT fx, FX_FLOAT fy); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual FWL_ERR SetThemeProvider(IFWL_ThemeProvider* pThemeProvider); + virtual int32_t GetCurSel(); + virtual FWL_ERR SetCurSel(int32_t iSel); + virtual FWL_ERR SetEditText(const CFX_WideString& wsText); + virtual int32_t GetEditTextLength() const; + virtual FWL_ERR GetEditText(CFX_WideString& wsText, + int32_t nStart = 0, + int32_t nCount = -1) const; + virtual FWL_ERR SetEditSelRange(int32_t nStart, int32_t nCount = -1); + virtual int32_t GetEditSelRange(int32_t nIndex, int32_t& nStart); + virtual int32_t GetEditLimit(); + virtual FWL_ERR SetEditLimit(int32_t nLimit); + virtual FWL_ERR EditDoClipboard(int32_t iCmd); + virtual FX_BOOL EditRedo(const CFX_ByteStringC& bsRecord); + virtual FX_BOOL EditUndo(const CFX_ByteStringC& bsRecord); + virtual IFWL_ListBox* GetListBoxt(); + virtual FX_BOOL AfterFocusShowDropList(); + virtual FX_ERR OpenDropDownList(FX_BOOL bActivate); + virtual FX_BOOL EditCanUndo(); + virtual FX_BOOL EditCanRedo(); + virtual FX_BOOL EditUndo(); + virtual FX_BOOL EditRedo(); + virtual FX_BOOL EditCanCopy(); + virtual FX_BOOL EditCanCut(); + virtual FX_BOOL EditCanSelectAll(); + virtual FX_BOOL EditCopy(CFX_WideString& wsCopy); + virtual FX_BOOL EditCut(CFX_WideString& wsCut); + virtual FX_BOOL EditPaste(const CFX_WideString& wsPaste); + virtual FX_BOOL EditSelectAll(); + virtual FX_BOOL EditDelete(); + virtual FX_BOOL EditDeSelect(); + virtual FWL_ERR GetBBox(CFX_RectF& rect); + virtual FWL_ERR EditModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved); + + protected: + void DrawStretchHandler(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix); + FX_FLOAT GetListHeight(); + void ShowDropList(FX_BOOL bActivate); + FX_BOOL IsDropListShowed(); + FX_BOOL IsDropDownStyle() const; + void MatchEditText(); + void SynchrEditText(int32_t iListItem); + void Layout(); + void ReSetTheme(); + void ReSetEditAlignment(); + void ReSetListItemAlignment(); + void ProcessSelChanged(FX_BOOL bLButtonUp); + void InitProxyForm(); + FWL_ERR DisForm_Initialize(); + void DisForm_InitComboList(); + void DisForm_InitComboEdit(); + void DisForm_ShowDropList(FX_BOOL bActivate); + FX_BOOL DisForm_IsDropListShowed(); + FWL_ERR DisForm_ModifyStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved); + FWL_ERR DisForm_Update(); + FX_DWORD DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy); + FWL_ERR DisForm_DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + FWL_ERR DisForm_GetBBox(CFX_RectF& rect); + void DisForm_Layout(); + + CFX_RectF m_rtClient; + CFX_RectF m_rtContent; + CFX_RectF m_rtBtn; + CFX_RectF m_rtList; + CFX_RectF m_rtProxy; + CFX_RectF m_rtHandler; + std::unique_ptr<IFWL_Edit> m_pEdit; + std::unique_ptr<IFWL_ListBox> m_pListBox; + IFWL_Form* m_pForm; + FX_BOOL m_bLButtonDown; + FX_BOOL m_bUpFormHandler; + int32_t m_iCurSel; + int32_t m_iBtnState; + FX_FLOAT m_fComboFormHandler; + FX_FLOAT m_fItemHeight; + FX_BOOL m_bNeedShowList; + CFWL_FormProxyImp* m_pProxy; + CFWL_ComboProxyImpDelegate* m_pListProxyDelegate; + + friend class CFWL_ComboListImp; + friend class CFWL_ComboEditImp; + friend class CFWL_ComboEditImpDelegate; + friend class CFWL_ComboListImpDelegate; + friend class CFWL_ComboBoxImpDelegate; + friend class CFWL_ComboProxyImpDelegate; +}; +class CFWL_ComboBoxImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_ComboBoxImpDelegate(CFWL_ComboBoxImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + void OnKey(CFWL_MsgKey* pMsg); + void DoSubCtrlKey(CFWL_MsgKey* pMsg); + + protected: + int32_t DisForm_OnProcessMessage(CFWL_Message* pMessage); + void DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg); + void DisForm_OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void DisForm_OnKey(CFWL_MsgKey* pMsg); + + protected: + CFWL_ComboBoxImp* m_pOwner; + friend class CFWL_ComboEditImpDelegate; + friend class CFWL_ComboListImpDelegate; +}; +class CFWL_ComboProxyImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_ComboProxyImpDelegate(IFWL_Form* pForm, CFWL_ComboBoxImp* pComboBox); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + void Reset() { m_bLButtonUpSelf = FALSE; } + + protected: + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnDeactive(CFWL_MsgDeactivate* pMsg); + void OnFocusChanged(CFWL_MsgKillFocus* pMsg, FX_BOOL bSet); + FX_BOOL m_bLButtonDown; + FX_BOOL m_bLButtonUpSelf; + FX_FLOAT m_fStartPos; + IFWL_Form* m_pForm; + CFWL_ComboBoxImp* m_pComboBox; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_COMBOBOXIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_datetimepickerimp.cpp b/xfa/src/fwl/basewidget/fwl_datetimepickerimp.cpp new file mode 100644 index 0000000000..c969418c3a --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_datetimepickerimp.cpp @@ -0,0 +1,1161 @@ +// 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/src/fwl/basewidget/fwl_datetimepickerimp.h" + +#include "xfa/include/fwl/basewidget/fwl_spinbutton.h" +#include "xfa/src/fwl/basewidget/fwl_editimp.h" +#include "xfa/src/fwl/basewidget/fwl_formproxyimp.h" +#include "xfa/src/fwl/basewidget/fwl_monthcalendarimp.h" +#include "xfa/src/fwl/core/fwl_formimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_panelimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" +#include "xfa/src/fwl/core/fwl_widgetmgrimp.h" + +#define FWL_DTP_WIDTH 100 +#define FWL_DTP_HEIGHT 20 + +// static +IFWL_DateTimePicker* IFWL_DateTimePicker::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_DateTimePicker* pDateTimePicker = new IFWL_DateTimePicker; + CFWL_DateTimePickerImp* pDateTimePickerImpl = + new CFWL_DateTimePickerImp(properties, pOuter); + pDateTimePicker->SetImpl(pDateTimePickerImpl); + pDateTimePickerImpl->SetInterface(pDateTimePicker); + return pDateTimePicker; +} + +// Static +IFWL_DateTimeForm* IFWL_DateTimeForm::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_DateTimeForm* pDateTimeForm = new IFWL_DateTimeForm; + CFWL_FormProxyImp* pFormProxyImpl = new CFWL_FormProxyImp(properties, pOuter); + pDateTimeForm->SetImpl(pFormProxyImpl); + pFormProxyImpl->SetInterface(pDateTimeForm); + return pDateTimeForm; +} + +// static +IFWL_DateTimeCalender* IFWL_DateTimeCalender::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_DateTimeCalender* pDateTimeCalendar = new IFWL_DateTimeCalender; + CFWL_DateTimeCalendar* pDateTimeCalendarImpl = + new CFWL_DateTimeCalendar(properties, pOuter); + pDateTimeCalendar->SetImpl(pDateTimeCalendarImpl); + pDateTimeCalendarImpl->SetInterface(pDateTimeCalendar); + return pDateTimeCalendar; +} + +// static +IFWL_DateTimeEdit* IFWL_DateTimeEdit::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_DateTimeEdit* pDateTimeEdit = new IFWL_DateTimeEdit; + CFWL_DateTimeEdit* pDateTimeEditImpl = + new CFWL_DateTimeEdit(properties, pOuter); + pDateTimeEdit->SetImpl(pDateTimeEditImpl); + pDateTimeEditImpl->SetInterface(pDateTimeEdit); + return pDateTimeEdit; +} + +IFWL_DateTimePicker::IFWL_DateTimePicker() {} +int32_t IFWL_DateTimePicker::CountSelRanges() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl()) + ->GetDataTimeEdit() + ->CountSelRanges(); +} +int32_t IFWL_DateTimePicker::GetSelRange(int32_t nIndex, int32_t& nStart) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl()) + ->GetDataTimeEdit() + ->GetSelRange(nIndex, nStart); +} +FWL_ERR IFWL_DateTimePicker::GetCurSel(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl()) + ->GetCurSel(iYear, iMonth, iDay); +} +FWL_ERR IFWL_DateTimePicker::SetCurSel(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl()) + ->SetCurSel(iYear, iMonth, iDay); +} +FWL_ERR IFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SetEditText(wsText); +} +FWL_ERR IFWL_DateTimePicker::GetEditText(CFX_WideString& wsText, + int32_t nStart, + int32_t nCount) const { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl()) + ->GetEditText(wsText, nStart, nCount); +} +FX_BOOL IFWL_DateTimePicker::CanUndo() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanUndo(); +} +FX_BOOL IFWL_DateTimePicker::CanRedo() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanRedo(); +} +FX_BOOL IFWL_DateTimePicker::Undo() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Undo(); +} +FX_BOOL IFWL_DateTimePicker::Redo() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Redo(); +} +FX_BOOL IFWL_DateTimePicker::CanCopy() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanCopy(); +} +FX_BOOL IFWL_DateTimePicker::CanCut() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanCut(); +} +FX_BOOL IFWL_DateTimePicker::CanSelectAll() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanSelectAll(); +} +FX_BOOL IFWL_DateTimePicker::Copy(CFX_WideString& wsCopy) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Copy(wsCopy); +} +FX_BOOL IFWL_DateTimePicker::Cut(CFX_WideString& wsCut) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Cut(wsCut); +} +FX_BOOL IFWL_DateTimePicker::Paste(const CFX_WideString& wsPaste) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Paste(wsPaste); +} +FX_BOOL IFWL_DateTimePicker::SelectAll() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SelectAll(); +} +FX_BOOL IFWL_DateTimePicker::Delete() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Delete(); +} +FX_BOOL IFWL_DateTimePicker::DeSelect() { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->DeSelect(); +} +FWL_ERR IFWL_DateTimePicker::GetBBox(CFX_RectF& rect) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->GetBBox(rect); +} +FWL_ERR IFWL_DateTimePicker::SetEditLimit(int32_t nLimit) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SetEditLimit(nLimit); +} +FWL_ERR IFWL_DateTimePicker::ModifyEditStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved) { + return static_cast<CFWL_DateTimePickerImp*>(GetImpl()) + ->ModifyEditStylesEx(dwStylesExAdded, dwStylesExRemoved); +} +CFWL_DateTimeEdit::CFWL_DateTimeEdit(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_EditImp(properties, pOuter) {} +FWL_ERR CFWL_DateTimeEdit::Initialize() { + m_pDelegate = new CFWL_DateTimeEditImpDelegate(this); + if (CFWL_EditImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimeEdit::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_EditImp::Finalize(); +} +CFWL_DateTimeEditImpDelegate::CFWL_DateTimeEditImpDelegate( + CFWL_DateTimeEdit* pOwner) + : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) {} +int32_t CFWL_DateTimeEditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) { + return DisForm_OnProcessMessage(pMessage); + } + FX_DWORD dwHashCode = pMessage->GetClassID(); + if (dwHashCode == FWL_MSGHASH_SetFocus || + dwHashCode == FWL_MSGHASH_KillFocus) { + IFWL_Widget* pOuter = m_pOwner->GetOuter(); + IFWL_WidgetDelegate* pDelegate = pOuter->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMessage); + } + return 1; +} +int32_t CFWL_DateTimeEditImpDelegate::DisForm_OnProcessMessage( + CFWL_Message* pMessage) { + FX_DWORD dwHashCode = pMessage->GetClassID(); + if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) { + if (dwHashCode == FWL_MSGHASH_Mouse) { + CFWL_MsgMouse* pMouse = static_cast<CFWL_MsgMouse*>(pMessage); + if (pMouse->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown || + pMouse->m_dwCmd == FWL_MSGMOUSECMD_RButtonDown) { + if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + } + CFWL_DateTimePickerImp* pDateTime = + static_cast<CFWL_DateTimePickerImp*>(m_pOwner->m_pOuter->GetImpl()); + if (pDateTime->IsMonthCalendarShowed()) { + CFX_RectF rtInvalidate; + pDateTime->GetWidgetRect(rtInvalidate); + pDateTime->ShowMonthCalendar(FALSE); + rtInvalidate.Offset(-rtInvalidate.left, -rtInvalidate.top); + pDateTime->Repaint(&rtInvalidate); + } + } + } else if (dwHashCode == FWL_MSGHASH_Key) { + return CFWL_EditImpDelegate::OnProcessMessage(pMessage); + } + } + return CFWL_EditImpDelegate::OnProcessMessage(pMessage); +} +CFWL_DateTimeCalendar::CFWL_DateTimeCalendar( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_MonthCalendarImp(properties, pOuter) {} +FWL_ERR CFWL_DateTimeCalendar::Initialize() { + if (CFWL_MonthCalendarImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + delete m_pDelegate; + m_pDelegate = new CFWL_DateTimeCalendarImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimeCalendar::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_MonthCalendarImp::Finalize(); +} +CFWL_DateTimeCalendarImpDelegate::CFWL_DateTimeCalendarImpDelegate( + CFWL_DateTimeCalendar* pOwner) + : CFWL_MonthCalendarImpDelegate(pOwner), m_pOwner(pOwner) { + m_bFlag = FALSE; +} +int32_t CFWL_DateTimeCalendarImpDelegate::OnProcessMessage( + CFWL_Message* pMessage) { + FX_DWORD dwCode = pMessage->GetClassID(); + if (dwCode == FWL_MSGHASH_SetFocus || dwCode == FWL_MSGHASH_KillFocus) { + IFWL_Widget* pOuter = m_pOwner->GetOuter(); + IFWL_WidgetDelegate* pDelegate = pOuter->SetDelegate(NULL); + return pDelegate->OnProcessMessage(pMessage); + } else if (dwCode == FWL_MSGHASH_Mouse) { + CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); + if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) { + OnLButtonDownEx(pMsg); + return 1; + } else if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonUp) { + OnLButtonUpEx(pMsg); + return 1; + } + } + return CFWL_MonthCalendarImpDelegate::OnProcessMessage(pMessage); +} +void CFWL_DateTimeCalendarImpDelegate::OnLButtonDownEx(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iLBtnPartStates = FWL_PARTSTATE_MCD_Pressed; + m_pOwner->PrevMonth(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } else if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iRBtnPartStates |= FWL_PARTSTATE_MCD_Pressed; + m_pOwner->NextMonth(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } else if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) { + if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoToday) == + 0) { + m_pOwner->JumpToToday(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + } else { + IFWL_DateTimePicker* pIPicker = + static_cast<IFWL_DateTimePicker*>(m_pOwner->m_pOuter); + CFWL_DateTimePickerImp* pPicker = + static_cast<CFWL_DateTimePickerImp*>(pIPicker->GetImpl()); + if (pPicker->IsMonthCalendarShowed()) { + m_bFlag = 1; + } + } +} +void CFWL_DateTimeCalendarImpDelegate::OnLButtonUpEx(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) { + return DisForm_OnLButtonUpEx(pMsg); + } + if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iLBtnPartStates = 0; + m_pOwner->Repaint(&m_pOwner->m_rtLBtn); + return; + } + if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iRBtnPartStates = 0; + m_pOwner->Repaint(&m_pOwner->m_rtRBtn); + return; + } + if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) { + return; + } + int32_t iOldSel = 0; + if (m_pOwner->m_arrSelDays.GetSize() > 0) { + iOldSel = m_pOwner->m_arrSelDays[0]; + } + int32_t iCurSel = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy); + CFX_RectF rt; + IFWL_DateTimePicker* pIPicker = + static_cast<IFWL_DateTimePicker*>(m_pOwner->m_pOuter); + CFWL_DateTimePickerImp* pPicker = + static_cast<CFWL_DateTimePickerImp*>(pIPicker->GetImpl()); + pPicker->m_pForm->GetWidgetRect(rt); + rt.Set(0, 0, rt.width, rt.height); + if (iCurSel > 0) { + FWL_DATEINFO* lpDatesInfo = + (FWL_DATEINFO*)m_pOwner->m_arrDates.GetAt(iCurSel - 1); + CFX_RectF rtInvalidate(lpDatesInfo->rect); + if (iOldSel > 0 && iOldSel <= m_pOwner->m_arrDates.GetSize()) { + lpDatesInfo = (FWL_DATEINFO*)m_pOwner->m_arrDates.GetAt(iOldSel - 1); + rtInvalidate.Union(lpDatesInfo->rect); + } + m_pOwner->AddSelDay(iCurSel); + if (!m_pOwner->m_pOuter) + return; + pPicker->ProcessSelChanged(m_pOwner->m_iCurYear, m_pOwner->m_iCurMonth, + iCurSel); + pPicker->ShowMonthCalendar(FALSE); + } else if (m_bFlag && (!rt.Contains(pMsg->m_fx, pMsg->m_fy))) { + IFWL_DateTimePicker* pIPicker = + static_cast<IFWL_DateTimePicker*>(m_pOwner->m_pOuter); + CFWL_DateTimePickerImp* pPicker = + static_cast<CFWL_DateTimePickerImp*>(pIPicker->GetImpl()); + pPicker->ShowMonthCalendar(FALSE); + } + m_bFlag = 0; +} +void CFWL_DateTimeCalendarImpDelegate::OnMouseMoveEx(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_MultiSelect) { + return; + } + FX_BOOL bRepaint = FALSE; + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, 0, 0); + if (m_pOwner->m_rtDates.Contains(pMsg->m_fx, pMsg->m_fy)) { + int32_t iHover = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy); + bRepaint = m_pOwner->m_iHovered != iHover; + if (bRepaint) { + if (m_pOwner->m_iHovered > 0) { + m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate); + } + if (iHover > 0) { + CFX_RectF rtDay; + m_pOwner->GetDayRect(iHover, rtDay); + if (rtInvalidate.IsEmpty()) { + rtInvalidate = rtDay; + } else { + rtInvalidate.Union(rtDay); + } + } + } + m_pOwner->m_iHovered = iHover; + CFWL_Event_DtpHoverChanged ev; + ev.hoverday = iHover; + m_pOwner->DispatchEvent(&ev); + } else { + bRepaint = m_pOwner->m_iHovered > 0; + if (bRepaint) { + m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate); + } + m_pOwner->m_iHovered = -1; + } + if (bRepaint && !rtInvalidate.IsEmpty()) { + m_pOwner->Repaint(&rtInvalidate); + } +} +int32_t CFWL_DateTimeCalendarImpDelegate::DisForm_OnProcessMessage( + CFWL_Message* pMessage) { + if (pMessage->GetClassID() == FWL_MSGHASH_Mouse) { + CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); + if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonUp) { + DisForm_OnLButtonUpEx(pMsg); + return 1; + } + } + return CFWL_MonthCalendarImpDelegate::OnProcessMessage(pMessage); +} +void CFWL_DateTimeCalendarImpDelegate::DisForm_OnLButtonUpEx( + CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iLBtnPartStates = 0; + m_pOwner->Repaint(&(m_pOwner->m_rtLBtn)); + return; + } + if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iRBtnPartStates = 0; + m_pOwner->Repaint(&(m_pOwner->m_rtRBtn)); + return; + } + if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) { + return; + } + int32_t iOldSel = 0; + if (m_pOwner->m_arrSelDays.GetSize() > 0) { + iOldSel = m_pOwner->m_arrSelDays[0]; + } + int32_t iCurSel = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy); + if (iCurSel > 0) { + FWL_DATEINFO* lpDatesInfo = + (FWL_DATEINFO*)m_pOwner->m_arrDates.GetAt(iCurSel - 1); + CFX_RectF rtInvalidate(lpDatesInfo->rect); + if (iOldSel > 0 && iOldSel <= m_pOwner->m_arrDates.GetSize()) { + lpDatesInfo = (FWL_DATEINFO*)m_pOwner->m_arrDates.GetAt(iOldSel - 1); + rtInvalidate.Union(lpDatesInfo->rect); + } + m_pOwner->AddSelDay(iCurSel); + CFWL_DateTimePickerImp* pDateTime = + static_cast<CFWL_DateTimePickerImp*>(m_pOwner->m_pOuter->GetImpl()); + pDateTime->ProcessSelChanged(m_pOwner->m_iCurYear, m_pOwner->m_iCurMonth, + iCurSel); + pDateTime->ShowMonthCalendar(FALSE); + } +} +CFWL_DateTimePickerImp::CFWL_DateTimePickerImp( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_iBtnState(1), + m_iYear(-1), + m_iMonth(-1), + m_iDay(-1), + m_bLBtnDown(FALSE), + m_pEdit(nullptr), + m_pMonthCal(nullptr), + m_pForm(nullptr) { + m_rtBtn.Set(0, 0, 0, 0); +} +CFWL_DateTimePickerImp::~CFWL_DateTimePickerImp() {} +FWL_ERR CFWL_DateTimePickerImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_DateTimePicker; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_DateTimePickerImp::GetClassID() const { + return FWL_CLASSHASH_DateTimePicker; +} +FWL_ERR CFWL_DateTimePickerImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_DateTimePickerImpDelegate(this); + m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat; + CFWL_WidgetImpProperties propMonth; + propMonth.m_dwStyles = FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border; + propMonth.m_dwStates = FWL_WGTSTATE_Invisible; + propMonth.m_pDataProvider = &m_MonthCalendarDP; + propMonth.m_pParent = m_pInterface; + propMonth.m_pThemeProvider = m_pProperties->m_pThemeProvider; + m_pMonthCal.reset(IFWL_DateTimeCalender::Create(propMonth, m_pInterface)); + m_pMonthCal->Initialize(); + CFX_RectF rtMonthCal; + m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE); + rtMonthCal.Set(0, 0, rtMonthCal.width, rtMonthCal.height); + m_pMonthCal->SetWidgetRect(rtMonthCal); + CFWL_WidgetImpProperties propEdit; + propEdit.m_pParent = m_pInterface; + propEdit.m_pThemeProvider = m_pProperties->m_pThemeProvider; + m_pEdit.reset(IFWL_DateTimeEdit::Create(propEdit, m_pInterface)); + m_pEdit->Initialize(); + RegisterEventTarget(m_pMonthCal.get()); + RegisterEventTarget(m_pEdit.get()); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::Finalize() { + if (m_pEdit) { + m_pEdit->Finalize(); + } + if (m_pMonthCal) { + m_pMonthCal->Finalize(); + } + if (m_pForm) { + m_pForm->Finalize(); + } + UnregisterEventTarget(); + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_DateTimePickerImp::GetWidgetRect(CFX_RectF& rect, + FX_BOOL bAutoSize) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_GetWidgetRect(rect, bAutoSize); + } + if (bAutoSize) { + rect.Set(0, 0, FWL_DTP_WIDTH, FWL_DTP_HEIGHT); + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::Update() { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_Update(); + } + if (m_iLock) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider); + GetClientRect(m_rtClient); + FX_FLOAT* pFWidth = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pFWidth) + return FWL_ERR_Indefinite; + FX_FLOAT fBtn = *pFWidth; + m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn - 1, + m_rtClient.height - 1); + CFX_RectF rtEdit; + rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn, + m_rtClient.height); + m_pEdit->SetWidgetRect(rtEdit); + ReSetEditAlignment(); + m_pEdit->Update(); + if (!(m_pMonthCal->GetThemeProvider())) { + m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider); + } + if (m_pProperties->m_pDataProvider) { + IFWL_DateTimePickerDP* pData = + static_cast<IFWL_DateTimePickerDP*>(m_pProperties->m_pDataProvider); + pData->GetToday(m_pInterface, m_MonthCalendarDP.m_iCurYear, + m_MonthCalendarDP.m_iCurMonth, m_MonthCalendarDP.m_iCurDay); + } + CFX_RectF rtMonthCal; + m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE); + CFX_RectF rtPopUp; + rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + FWL_DTP_HEIGHT, + rtMonthCal.width, rtMonthCal.height); + m_pMonthCal->SetWidgetRect(rtPopUp); + m_pMonthCal->Update(); + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_DateTimePickerImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_HitTest(fx, fy); + } + if (m_rtClient.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + if (IsMonthCalendarShowed()) { + CFX_RectF rect; + m_pMonthCal->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + } + return FWL_WGTHITTEST_Unknown; +} +FWL_ERR CFWL_DateTimePickerImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_DTP_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_DTP_Edge, pTheme, pMatrix); + } + if (!m_rtBtn.IsEmpty()) { + DrawDropDownButton(pGraphics, pTheme, pMatrix); + } + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_DrawWidget(pGraphics, pMatrix); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::SetThemeProvider(IFWL_ThemeProvider* pTP) { + m_pProperties->m_pThemeProvider = pTP; + m_pMonthCal->SetThemeProvider(pTP); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::GetCurSel(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay) { + iYear = m_iYear; + iMonth = m_iMonth; + iDay = m_iDay; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::SetCurSel(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + if (iYear <= 0 || iYear >= 3000) + return FWL_ERR_Indefinite; + if (iMonth <= 0 || iMonth >= 13) + return FWL_ERR_Indefinite; + if (iDay <= 0 || iDay >= 32) + return FWL_ERR_Indefinite; + m_iYear = iYear; + m_iMonth = iMonth; + m_iDay = iDay; + m_pMonthCal->SetSelect(iYear, iMonth, iDay); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::SetEditText(const CFX_WideString& wsText) { + if (!m_pEdit) + return FWL_ERR_Indefinite; + int32_t iRet = m_pEdit->SetText(wsText); + Repaint(&m_rtClient); + CFWL_Event_DtpEditChanged ev; + ev.m_wsText = wsText; + DispatchEvent(&ev); + return iRet; +} +FWL_ERR CFWL_DateTimePickerImp::GetEditText(CFX_WideString& wsText, + int32_t nStart, + int32_t nCount) const { + if (m_pEdit) { + return m_pEdit->GetText(wsText, nStart, nCount); + } + return FWL_ERR_Indefinite; +} +FX_BOOL CFWL_DateTimePickerImp::CanUndo() { + return m_pEdit->CanUndo(); +} +FX_BOOL CFWL_DateTimePickerImp::CanRedo() { + return m_pEdit->CanRedo(); +} +FX_BOOL CFWL_DateTimePickerImp::Undo() { + return m_pEdit->Undo(); +} +FX_BOOL CFWL_DateTimePickerImp::Redo() { + return m_pEdit->Redo(); +} +FX_BOOL CFWL_DateTimePickerImp::CanCopy() { + int32_t nCount = m_pEdit->CountSelRanges(); + return nCount > 0; +} +FX_BOOL CFWL_DateTimePickerImp::CanCut() { + if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) { + return FALSE; + } + int32_t nCount = m_pEdit->CountSelRanges(); + return nCount > 0; +} +FX_BOOL CFWL_DateTimePickerImp::CanSelectAll() { + return m_pEdit->GetTextLength() > 0; +} +FX_BOOL CFWL_DateTimePickerImp::Copy(CFX_WideString& wsCopy) { + return m_pEdit->Copy(wsCopy); +} +FX_BOOL CFWL_DateTimePickerImp::Cut(CFX_WideString& wsCut) { + return m_pEdit->Cut(wsCut); +} +FX_BOOL CFWL_DateTimePickerImp::Paste(const CFX_WideString& wsPaste) { + return m_pEdit->Paste(wsPaste); +} +FX_BOOL CFWL_DateTimePickerImp::SelectAll() { + return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded; +} +FX_BOOL CFWL_DateTimePickerImp::Delete() { + return m_pEdit->ClearText() == FWL_ERR_Succeeded; +} +FX_BOOL CFWL_DateTimePickerImp::DeSelect() { + return m_pEdit->ClearSelections() == FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::GetBBox(CFX_RectF& rect) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_GetBBox(rect); + } + rect = m_pProperties->m_rtWidget; + if (IsMonthCalendarShowed()) { + CFX_RectF rtMonth; + m_pMonthCal->GetWidgetRect(rtMonth); + rtMonth.Offset(m_pProperties->m_rtWidget.left, + m_pProperties->m_rtWidget.top); + rect.Union(rtMonth); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::SetEditLimit(int32_t nLimit) { + return m_pEdit->SetLimit(nLimit); +} +FWL_ERR CFWL_DateTimePickerImp::ModifyEditStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved) { + return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); +} +void CFWL_DateTimePickerImp::DrawDropDownButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_Spin) == + FWL_STYLEEXT_DTP_Spin) { + CFWL_WidgetImpProperties prop; + prop.m_dwStyleExes |= FWL_STYLEEXE_SPB_Vert; + prop.m_pParent = m_pInterface; + prop.m_rtWidget = m_rtBtn; + IFWL_SpinButton* pSpin = IFWL_SpinButton::Create(prop, m_pInterface); + pSpin->Initialize(); + } else { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_DTP_DropDownButton; + param.m_dwStates = m_iBtnState; + param.m_pGraphics = pGraphics; + param.m_rtPart = m_rtBtn; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶m); + } +} +void CFWL_DateTimePickerImp::FormatDateString(int32_t iYear, + int32_t iMonth, + int32_t iDay, + CFX_WideString& wsText) { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat) == + FWL_STYLEEXT_DTP_ShortDateFormat) { + wsText.Format(L"%d-%d-%d", iYear, iMonth, iDay); + } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) == + FWL_STYLEEXT_DTP_LongDateFormat) { + wsText.Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay); + } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_TimeFormat) == + FWL_STYLEEXT_DTP_TimeFormat) { + } +} +void CFWL_DateTimePickerImp::ShowMonthCalendar(FX_BOOL bActivate) { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_ShowMonthCalendar(bActivate); + } + if (IsMonthCalendarShowed() == bActivate) { + return; + } + if (!m_pForm) { + InitProxyForm(); + } + if (bActivate) { + CFX_RectF rtMonth; + m_pMonthCal->GetWidgetRect(rtMonth); + CFX_RectF rtAnchor; + rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width, + m_pProperties->m_rtWidget.height); + GetPopupPos(0, rtMonth.height, rtAnchor, rtMonth); + m_pForm->SetWidgetRect(rtMonth); + rtMonth.left = rtMonth.top = 0; + m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate); + m_pMonthCal->SetWidgetRect(rtMonth); + m_pMonthCal->Update(); + m_pForm->DoModal(); + } else { + m_pForm->EndDoModal(); + } +} +FX_BOOL CFWL_DateTimePickerImp::IsMonthCalendarShowed() { + if (m_pWidgetMgr->IsFormDisabled()) { + return DisForm_IsMonthCalendarShowed(); + } + if (!m_pForm) + return FALSE; + return !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible); +} +void CFWL_DateTimePickerImp::ReSetEditAlignment() { + if (!m_pEdit) + return; + FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes; + FX_DWORD dwAdd = 0; + switch (dwStylExes & FWL_STYLEEXT_DTP_EditHAlignMask) { + case FWL_STYLEEXT_DTP_EditHCenter: { + dwAdd |= FWL_STYLEEXT_EDT_HCenter; + break; + } + case FWL_STYLEEXT_DTP_EditHFar: { + dwAdd |= FWL_STYLEEXT_EDT_HFar; + break; + } + default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; } + } + switch (dwStylExes & FWL_STYLEEXT_DTP_EditVAlignMask) { + case FWL_STYLEEXT_DTP_EditVCenter: { + dwAdd |= FWL_STYLEEXT_EDT_VCenter; + break; + } + case FWL_STYLEEXT_DTP_EditVFar: { + dwAdd |= FWL_STYLEEXT_EDT_VFar; + break; + } + default: { dwAdd |= FWL_STYLEEXT_EDT_VNear; } + } + if (dwStylExes & FWL_STYLEEXT_DTP_EditJustified) { + dwAdd |= FWL_STYLEEXT_EDT_Justified; + } + if (dwStylExes & FWL_STYLEEXT_DTP_EditDistributed) { + dwAdd |= FWL_STYLEEXT_EDT_Distributed; + } + m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask | + FWL_STYLEEXT_EDT_HAlignModeMask | + FWL_STYLEEXT_EDT_VAlignMask); +} +void CFWL_DateTimePickerImp::ProcessSelChanged(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + m_iYear = iYear; + m_iMonth = iMonth; + m_iDay = iDay; + CFX_WideString wsText; + FormatDateString(m_iYear, m_iMonth, m_iDay, wsText); + m_pEdit->SetText(wsText); + m_pEdit->Update(); + Repaint(&m_rtClient); + CFWL_Event_DtpSelectChanged ev; + ev.m_pSrcTarget = m_pInterface; + ev.iYear = m_iYear; + ev.iMonth = m_iMonth; + ev.iDay = m_iDay; + DispatchEvent(&ev); +} +void CFWL_DateTimePickerImp::InitProxyForm() { + if (m_pForm) + return; + if (!m_pMonthCal) + return; + CFWL_WidgetImpProperties propForm; + propForm.m_dwStyles = FWL_WGTSTYLE_Popup; + propForm.m_dwStates = FWL_WGTSTATE_Invisible; + propForm.m_pOwner = m_pInterface; + m_pForm.reset(IFWL_DateTimeForm::Create(propForm, m_pMonthCal.get())); + m_pForm->Initialize(); + m_pMonthCal->SetParent(m_pForm.get()); +} +IFWL_DateTimeEdit* CFWL_DateTimePickerImp::GetDataTimeEdit() { + return m_pEdit.get(); +} +FWL_ERR CFWL_DateTimePickerImp::DisForm_Initialize() { + m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat; + DisForm_InitDateTimeCalendar(); + DisForm_InitDateTimeEdit(); + RegisterEventTarget(m_pMonthCal.get()); + RegisterEventTarget(m_pEdit.get()); + return FWL_ERR_Succeeded; +} +void CFWL_DateTimePickerImp::DisForm_InitDateTimeCalendar() { + if (m_pMonthCal) { + return; + } + CFWL_WidgetImpProperties propMonth; + propMonth.m_dwStyles = + FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border | FWL_WGTSTYLE_EdgeSunken; + propMonth.m_dwStates = FWL_WGTSTATE_Invisible; + propMonth.m_pParent = m_pInterface; + propMonth.m_pDataProvider = &m_MonthCalendarDP; + propMonth.m_pThemeProvider = m_pProperties->m_pThemeProvider; + m_pMonthCal.reset(IFWL_DateTimeCalender::Create(propMonth, m_pInterface)); + m_pMonthCal->Initialize(); + CFX_RectF rtMonthCal; + m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE); + rtMonthCal.Set(0, 0, rtMonthCal.width, rtMonthCal.height); + m_pMonthCal->SetWidgetRect(rtMonthCal); +} +void CFWL_DateTimePickerImp::DisForm_InitDateTimeEdit() { + if (m_pEdit) { + return; + } + CFWL_WidgetImpProperties propEdit; + propEdit.m_pParent = m_pInterface; + propEdit.m_pThemeProvider = m_pProperties->m_pThemeProvider; + m_pEdit.reset(IFWL_DateTimeEdit::Create(propEdit, m_pInterface)); + m_pEdit->Initialize(); +} +FX_BOOL CFWL_DateTimePickerImp::DisForm_IsMonthCalendarShowed() { + if (!m_pMonthCal) + return FALSE; + return !(m_pMonthCal->GetStates() & FWL_WGTSTATE_Invisible); +} +void CFWL_DateTimePickerImp::DisForm_ShowMonthCalendar(FX_BOOL bActivate) { + FX_BOOL bShowed = IsMonthCalendarShowed(); + if (bShowed == bActivate) { + return; + } + if (bActivate) { + CFX_RectF rtMonthCal; + m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE); + FX_FLOAT fPopupMin = rtMonthCal.height; + FX_FLOAT fPopupMax = rtMonthCal.height; + CFX_RectF rtAnchor(m_pProperties->m_rtWidget); + rtAnchor.width = rtMonthCal.width; + rtMonthCal.left = m_rtClient.left; + rtMonthCal.top = rtAnchor.Height(); + GetPopupPos(fPopupMin, fPopupMax, rtAnchor, rtMonthCal); + m_pMonthCal->SetWidgetRect(rtMonthCal); + if (m_iYear > 0 && m_iMonth > 0 && m_iDay > 0) { + m_pMonthCal->SetSelect(m_iYear, m_iMonth, m_iDay); + } + m_pMonthCal->Update(); + } + m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate); + if (bActivate) { + CFWL_MsgSetFocus msg; + msg.m_pDstTarget = m_pMonthCal.get(); + msg.m_pSrcTarget = m_pEdit.get(); + IFWL_WidgetDelegate* pDelegate = m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(&msg); + } + CFX_RectF rtInvalidate, rtCal; + rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width, + m_pProperties->m_rtWidget.height); + m_pMonthCal->GetWidgetRect(rtCal); + rtInvalidate.Union(rtCal); + rtInvalidate.Inflate(2, 2); + Repaint(&rtInvalidate); +} +FX_DWORD CFWL_DateTimePickerImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) { + CFX_RectF rect; + rect.Set(0, 0, m_pProperties->m_rtWidget.width, + m_pProperties->m_rtWidget.height); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_Edit; + } + if (DisForm_IsNeedShowButton()) { + rect.width += m_fBtn; + } + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + if (IsMonthCalendarShowed()) { + m_pMonthCal->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + } + return FWL_WGTHITTEST_Unknown; +} +FX_BOOL CFWL_DateTimePickerImp::DisForm_IsNeedShowButton() { + FX_BOOL bFocus = m_pProperties->m_dwStates & FWL_WGTSTATE_Focused || + m_pMonthCal->GetStates() & FWL_WGTSTATE_Focused || + m_pEdit->GetStates() & FWL_WGTSTATE_Focused; + return bFocus; +} +FWL_ERR CFWL_DateTimePickerImp::DisForm_Update() { + if (m_iLock) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider); + GetClientRect(m_rtClient); + m_pEdit->SetWidgetRect(m_rtClient); + ReSetEditAlignment(); + m_pEdit->Update(); + if (m_pMonthCal->GetThemeProvider() == NULL) { + m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider); + } + if (m_pProperties->m_pDataProvider) { + IFWL_DateTimePickerDP* pData = + static_cast<IFWL_DateTimePickerDP*>(m_pProperties->m_pDataProvider); + pData->GetToday(m_pInterface, m_MonthCalendarDP.m_iCurYear, + m_MonthCalendarDP.m_iCurMonth, m_MonthCalendarDP.m_iCurDay); + } + FX_FLOAT* pWidth = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pWidth) + return 0; + m_fBtn = *pWidth; + CFX_RectF rtMonthCal; + m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE); + CFX_RectF rtPopUp; + rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + FWL_DTP_HEIGHT, + rtMonthCal.width, rtMonthCal.height); + m_pMonthCal->SetWidgetRect(rtPopUp); + m_pMonthCal->Update(); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::DisForm_GetWidgetRect(CFX_RectF& rect, + FX_BOOL bAutoSize) { + rect = m_pProperties->m_rtWidget; + if (DisForm_IsNeedShowButton()) { + rect.width += m_fBtn; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::DisForm_GetBBox(CFX_RectF& rect) { + rect = m_pProperties->m_rtWidget; + if (DisForm_IsNeedShowButton()) { + rect.width += m_fBtn; + } + if (IsMonthCalendarShowed()) { + CFX_RectF rtMonth; + m_pMonthCal->GetWidgetRect(rtMonth); + rtMonth.Offset(m_pProperties->m_rtWidget.left, + m_pProperties->m_rtWidget.top); + rect.Union(rtMonth); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_DateTimePickerImp::DisForm_DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (m_pEdit) { + CFX_RectF rtEdit; + m_pEdit->GetWidgetRect(rtEdit); + CFX_Matrix mt; + mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top); + if (pMatrix) { + mt.Concat(*pMatrix); + } + m_pEdit->DrawWidget(pGraphics, &mt); + } + if (IsMonthCalendarShowed()) { + CFX_RectF rtMonth; + m_pMonthCal->GetWidgetRect(rtMonth); + CFX_Matrix mt; + mt.Set(1, 0, 0, 1, rtMonth.left, rtMonth.top); + if (pMatrix) { + mt.Concat(*pMatrix); + } + m_pMonthCal->DrawWidget(pGraphics, &mt); + } + return FWL_ERR_Succeeded; +} +CFWL_DateTimePickerImpDelegate::CFWL_DateTimePickerImpDelegate( + CFWL_DateTimePickerImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_DateTimePickerImpDelegate::OnProcessMessage( + CFWL_Message* pMessage) { + if (!pMessage) + return 0; + 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* pMouse = static_cast<CFWL_MsgMouse*>(pMessage); + FX_DWORD dwCmd = pMouse->m_dwCmd; + switch (dwCmd) { + case FWL_MSGMOUSECMD_LButtonDown: { + OnLButtonDown(pMouse); + break; + } + case FWL_MSGMOUSECMD_LButtonUp: { + OnLButtonUp(pMouse); + break; + } + case FWL_MSGMOUSECMD_MouseMove: { + OnMouseMove(pMouse); + break; + } + case FWL_MSGMOUSECMD_MouseLeave: { + OnMouseLeave(pMouse); + break; + } + default: {} + } + break; + } + default: + break; + } + if (dwMsgCode == FWL_MSGHASH_Key && + m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) { + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + return pDelegate->OnProcessMessage(pMessage); + } + return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); +} +FWL_ERR CFWL_DateTimePickerImpDelegate::OnDrawWidget( + CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_DateTimePickerImpDelegate::OnFocusChanged(CFWL_Message* pMsg, + FX_BOOL bSet) { + if (!pMsg) + return; + if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) { + return DisForm_OnFocusChanged(pMsg, bSet); + } + if (bSet) { + m_pOwner->m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } else { + m_pOwner->m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + if (pMsg->m_pSrcTarget == m_pOwner->m_pMonthCal.get() && + m_pOwner->IsMonthCalendarShowed()) { + m_pOwner->ShowMonthCalendar(FALSE); + } + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_DateTimePickerImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + if (!pMsg) + return; + if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + m_pOwner->SetFocus(TRUE); + } + if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + if (m_pOwner->IsMonthCalendarShowed()) { + m_pOwner->ShowMonthCalendar(FALSE); + CFWL_Event_DtpCloseUp ev; + m_pOwner->DispatchEvent(&ev); + } else { + if (!(m_pOwner->m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_DTP_TimeFormat)) { + m_pOwner->ShowMonthCalendar(TRUE); + CFWL_Event_DtpDropDown ev; + m_pOwner->DispatchEvent(&ev); + } else { + } + m_pOwner->m_bLBtnDown = TRUE; + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + } +} +void CFWL_DateTimePickerImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + if (!pMsg) + return; + m_pOwner->m_bLBtnDown = FALSE; + if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Hovered; + } else { + m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Normal; + } + m_pOwner->Repaint(&m_pOwner->m_rtBtn); +} +void CFWL_DateTimePickerImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + } else { + m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Normal; + } + m_pOwner->Repaint(&m_pOwner->m_rtBtn); +} +void CFWL_DateTimePickerImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { + if (!pMsg) + return; + m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Normal; + m_pOwner->Repaint(&m_pOwner->m_rtBtn); +} +void CFWL_DateTimePickerImpDelegate::DisForm_OnFocusChanged(CFWL_Message* pMsg, + FX_BOOL bSet) { + CFX_RectF rtInvalidate(m_pOwner->m_rtBtn); + if (bSet) { + m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + if (m_pOwner->m_pEdit && + !(m_pOwner->m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)) { + m_pOwner->m_rtBtn.Set(m_pOwner->m_pProperties->m_rtWidget.width, 0, + m_pOwner->m_fBtn, + m_pOwner->m_pProperties->m_rtWidget.height - 1); + } + rtInvalidate = m_pOwner->m_rtBtn; + pMsg->m_pDstTarget = m_pOwner->m_pEdit.get(); + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMsg); + } else { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; + m_pOwner->m_rtBtn.Set(0, 0, 0, 0); + if (m_pOwner->DisForm_IsMonthCalendarShowed()) { + m_pOwner->ShowMonthCalendar(FALSE); + } + if (m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) { + pMsg->m_pSrcTarget = m_pOwner->m_pEdit.get(); + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMsg); + } + } + rtInvalidate.Inflate(2, 2); + m_pOwner->Repaint(&rtInvalidate); +} diff --git a/xfa/src/fwl/basewidget/fwl_datetimepickerimp.h b/xfa/src/fwl/basewidget/fwl_datetimepickerimp.h new file mode 100644 index 0000000000..4bc1063db5 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_datetimepickerimp.h @@ -0,0 +1,235 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_DATETIMEPICKERIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_DATETIMEPICKERIMP_H_ + +#include <memory> + +#include "xfa/include/fwl/core/fwl_form.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/include/fwl/basewidget/fwl_datetimepicker.h" +#include "xfa/include/fwl/basewidget/fwl_edit.h" +#include "xfa/include/fwl/basewidget/fwl_monthcalendar.h" +#include "xfa/src/fwl/basewidget/fwl_editimp.h" +#include "xfa/src/fwl/basewidget/fwl_monthcalendarimp.h" + +class CFWL_WidgetImp; +class CFWL_WidgetImpProperties; +class CFWL_WidgetImpDelegate; +class CFWL_DateTimeEdit; +class CFWL_DateTimeEditImpDelegate; +class CFWL_DateTimeCalendar; +class CFWL_DateTimeCalendarImpDelegate; +class CFWL_DateTimePickerImp; +class CFWL_DateTimePickerImpDelegate; + +class IFWL_DateTimeForm : public IFWL_Form { + public: + static IFWL_DateTimeForm* Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + + protected: + IFWL_DateTimeForm() {} +}; + +class IFWL_DateTimeCalender : public IFWL_MonthCalendar { + public: + static IFWL_DateTimeCalender* Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + + protected: + IFWL_DateTimeCalender() {} +}; + +class IFWL_DateTimeEdit : public IFWL_Edit { + public: + static IFWL_DateTimeEdit* Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + + protected: + IFWL_DateTimeEdit() {} +}; + +class CFWL_DateTimeEdit : public CFWL_EditImp { + public: + CFWL_DateTimeEdit(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + + protected: + friend class CFWL_DateTimeEditImpDelegate; +}; +class CFWL_DateTimeEditImpDelegate : public CFWL_EditImpDelegate { + public: + CFWL_DateTimeEditImpDelegate(CFWL_DateTimeEdit* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + + private: + int32_t DisForm_OnProcessMessage(CFWL_Message* pMessage); + + protected: + CFWL_DateTimeEdit* m_pOwner; +}; +class CFWL_DateTimeCalendar : public CFWL_MonthCalendarImp { + public: + CFWL_DateTimeCalendar(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + + protected: + friend class CFWL_DateTimeCalendarImpDelegate; +}; +class CFWL_DateTimeCalendarImpDelegate : public CFWL_MonthCalendarImpDelegate { + public: + CFWL_DateTimeCalendarImpDelegate(CFWL_DateTimeCalendar* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + + void OnLButtonDownEx(CFWL_MsgMouse* pMsg); + void OnLButtonUpEx(CFWL_MsgMouse* pMsg); + void OnMouseMoveEx(CFWL_MsgMouse* pMsg); + + private: + int32_t DisForm_OnProcessMessage(CFWL_Message* pMessage); + void DisForm_OnLButtonUpEx(CFWL_MsgMouse* pMsg); + + protected: + CFWL_DateTimeCalendar* m_pOwner; + FX_BOOL m_bFlag; +}; +class CFWL_DateTimePickerImp : public CFWL_WidgetImp { + public: + CFWL_DateTimePickerImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual ~CFWL_DateTimePickerImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FX_DWORD HitTest(FX_FLOAT fx, FX_FLOAT fy); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual FWL_ERR SetThemeProvider(IFWL_ThemeProvider* pTP); + virtual FWL_ERR GetCurSel(int32_t& iYear, int32_t& iMonth, int32_t& iDay); + virtual FWL_ERR SetCurSel(int32_t iYear, int32_t iMonth, int32_t iDay); + virtual FWL_ERR SetEditText(const CFX_WideString& wsText); + virtual FWL_ERR GetEditText(CFX_WideString& wsText, + int32_t nStart = 0, + int32_t nCount = -1) const; + + public: + virtual FX_BOOL CanUndo(); + virtual FX_BOOL CanRedo(); + virtual FX_BOOL Undo(); + virtual FX_BOOL Redo(); + virtual FX_BOOL CanCopy(); + virtual FX_BOOL CanCut(); + virtual FX_BOOL CanSelectAll(); + virtual FX_BOOL Copy(CFX_WideString& wsCopy); + virtual FX_BOOL Cut(CFX_WideString& wsCut); + virtual FX_BOOL Paste(const CFX_WideString& wsPaste); + virtual FX_BOOL SelectAll(); + virtual FX_BOOL Delete(); + virtual FX_BOOL DeSelect(); + virtual FWL_ERR GetBBox(CFX_RectF& rect); + virtual FWL_ERR SetEditLimit(int32_t nLimit); + virtual FWL_ERR ModifyEditStylesEx(FX_DWORD dwStylesExAdded, + FX_DWORD dwStylesExRemoved); + + public: + IFWL_DateTimeEdit* GetDataTimeEdit(); + + protected: + void DrawDropDownButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void FormatDateString(int32_t iYear, + int32_t iMonth, + int32_t iDay, + CFX_WideString& wsText); + void ShowMonthCalendar(FX_BOOL bActivate); + FX_BOOL IsMonthCalendarShowed(); + void ReSetEditAlignment(); + void InitProxyForm(); + void ProcessSelChanged(int32_t iYear, int32_t iMonth, int32_t iDay); + + private: + FWL_ERR DisForm_Initialize(); + void DisForm_InitDateTimeCalendar(); + void DisForm_InitDateTimeEdit(); + FX_BOOL DisForm_IsMonthCalendarShowed(); + void DisForm_ShowMonthCalendar(FX_BOOL bActivate); + FX_DWORD DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy); + FX_BOOL DisForm_IsNeedShowButton(); + FWL_ERR DisForm_Update(); + FWL_ERR DisForm_GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + FWL_ERR DisForm_GetBBox(CFX_RectF& rect); + FWL_ERR DisForm_DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + + protected: + CFX_RectF m_rtBtn; + CFX_RectF m_rtClient; + int32_t m_iBtnState; + int32_t m_iYear; + int32_t m_iMonth; + int32_t m_iDay; + FX_BOOL m_bLBtnDown; + std::unique_ptr<IFWL_DateTimeEdit> m_pEdit; + std::unique_ptr<IFWL_DateTimeCalender> m_pMonthCal; + std::unique_ptr<IFWL_DateTimeForm> m_pForm; + FX_FLOAT m_fBtn; + class CFWL_MonthCalendarImpDP : public IFWL_MonthCalendarDP { + public: + CFWL_MonthCalendarImpDP() { + m_iCurYear = 2010; + m_iCurMonth = 3; + m_iCurDay = 29; + } + virtual FWL_ERR GetCaption(IFWL_Widget* pWidget, + CFX_WideString& wsCaption) { + return FWL_ERR_Succeeded; + } + virtual int32_t GetCurDay(IFWL_Widget* pWidget) { return m_iCurDay; } + virtual int32_t GetCurMonth(IFWL_Widget* pWidget) { return m_iCurMonth; } + virtual int32_t GetCurYear(IFWL_Widget* pWidget) { return m_iCurYear; } + int32_t m_iCurDay; + int32_t m_iCurYear; + int32_t m_iCurMonth; + }; + + CFWL_MonthCalendarImpDP m_MonthCalendarDP; + friend class CFWL_DateTimeEditImpDelegate; + friend class CFWL_DateTimeCalendar; + friend class CFWL_DateTimeCalendarImpDelegate; + friend class CFWL_DateTimePickerImpDelegate; +}; +class CFWL_DateTimePickerImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_DateTimePickerImpDelegate(CFWL_DateTimePickerImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + + CFWL_DateTimePickerImp* m_pOwner; + + private: + void DisForm_OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_DATETIMEPICKERIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_editimp.cpp b/xfa/src/fwl/basewidget/fwl_editimp.cpp new file mode 100644 index 0000000000..5afaee1357 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_editimp.cpp @@ -0,0 +1,2151 @@ +// 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/src/fwl/basewidget/fwl_editimp.h" + +#include <algorithm> + +#include "xfa/include/fwl/basewidget/fwl_caret.h" +#include "xfa/include/fwl/basewidget/fwl_datetimepicker.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fdp/include/fde_rdr.h" +#include "xfa/src/fdp/include/fde_rdv.h" +#include "xfa/src/fee/include/ifde_txtedtpage.h" +#include "xfa/src/fwl/basewidget/fwl_caretimp.h" +#include "xfa/src/fwl/basewidget/fwl_comboboximp.h" +#include "xfa/src/fwl/basewidget/fwl_scrollbarimp.h" +#include "xfa/src/fwl/core/fwl_appimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_threadimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" +#include "xfa/src/fwl/core/fwl_widgetmgrimp.h" + +// static +IFWL_Edit* IFWL_Edit::Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_Edit* pEdit = new IFWL_Edit; + CFWL_EditImp* pEditImpl = new CFWL_EditImp(properties, pOuter); + pEdit->SetImpl(pEditImpl); + pEditImpl->SetInterface(pEdit); + return pEdit; +} +// static +IFWL_Edit* IFWL_Edit::CreateComboEdit( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_Edit* pEdit = new IFWL_Edit; + CFWL_EditImp* pComboEditImpl = new CFWL_ComboEditImp(properties, pOuter); + pEdit->SetImpl(pComboEditImpl); + pComboEditImpl->SetInterface(pEdit); + return pEdit; +} +IFWL_Edit::IFWL_Edit() {} +FWL_ERR IFWL_Edit::SetText(const CFX_WideString& wsText) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetText(wsText); +} +int32_t IFWL_Edit::GetTextLength() const { + return static_cast<CFWL_EditImp*>(GetImpl())->GetTextLength(); +} +FWL_ERR IFWL_Edit::GetText(CFX_WideString& wsText, + int32_t nStart, + int32_t nCount) const { + return static_cast<CFWL_EditImp*>(GetImpl())->GetText(wsText, nStart, nCount); +} +FWL_ERR IFWL_Edit::ClearText() { + return static_cast<CFWL_EditImp*>(GetImpl())->ClearText(); +} +int32_t IFWL_Edit::GetCaretPos() const { + return static_cast<CFWL_EditImp*>(GetImpl())->GetCaretPos(); +} +int32_t IFWL_Edit::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetCaretPos(nIndex, bBefore); +} +FWL_ERR IFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) { + return static_cast<CFWL_EditImp*>(GetImpl())->AddSelRange(nStart, nCount); +} +int32_t IFWL_Edit::CountSelRanges() { + return static_cast<CFWL_EditImp*>(GetImpl())->CountSelRanges(); +} +int32_t IFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) { + return static_cast<CFWL_EditImp*>(GetImpl())->GetSelRange(nIndex, nStart); +} +FWL_ERR IFWL_Edit::ClearSelections() { + return static_cast<CFWL_EditImp*>(GetImpl())->ClearSelections(); +} +int32_t IFWL_Edit::GetLimit() { + return static_cast<CFWL_EditImp*>(GetImpl())->GetLimit(); +} +FWL_ERR IFWL_Edit::SetLimit(int32_t nLimit) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetLimit(nLimit); +} +FWL_ERR IFWL_Edit::SetAliasChar(FX_WCHAR wAlias) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetAliasChar(wAlias); +} +FWL_ERR IFWL_Edit::Insert(int32_t nStart, + const FX_WCHAR* lpText, + int32_t nLen) { + return static_cast<CFWL_EditImp*>(GetImpl())->Insert(nStart, lpText, nLen); +} +FWL_ERR IFWL_Edit::DeleteSelections() { + return static_cast<CFWL_EditImp*>(GetImpl())->DeleteSelections(); +} +FWL_ERR IFWL_Edit::DeleteRange(int32_t nStart, int32_t nCount) { + return static_cast<CFWL_EditImp*>(GetImpl())->DeleteRange(nStart, nCount); +} +FWL_ERR IFWL_Edit::ReplaceSelections(const CFX_WideStringC& wsReplace) { + return static_cast<CFWL_EditImp*>(GetImpl())->ReplaceSelections(wsReplace); +} +FWL_ERR IFWL_Edit::Replace(int32_t nStart, + int32_t nLen, + const CFX_WideStringC& wsReplace) { + return static_cast<CFWL_EditImp*>(GetImpl()) + ->Replace(nStart, nLen, wsReplace); +} +FWL_ERR IFWL_Edit::DoClipboard(int32_t iCmd) { + return static_cast<CFWL_EditImp*>(GetImpl())->DoClipboard(iCmd); +} +FX_BOOL IFWL_Edit::Copy(CFX_WideString& wsCopy) { + return static_cast<CFWL_EditImp*>(GetImpl())->Copy(wsCopy); +} +FX_BOOL IFWL_Edit::Cut(CFX_WideString& wsCut) { + return static_cast<CFWL_EditImp*>(GetImpl())->Cut(wsCut); +} +FX_BOOL IFWL_Edit::Paste(const CFX_WideString& wsPaste) { + return static_cast<CFWL_EditImp*>(GetImpl())->Paste(wsPaste); +} +FX_BOOL IFWL_Edit::Delete() { + return static_cast<CFWL_EditImp*>(GetImpl())->Delete(); +} +FX_BOOL IFWL_Edit::Redo(const CFX_ByteStringC& bsRecord) { + return static_cast<CFWL_EditImp*>(GetImpl())->Redo(bsRecord); +} +FX_BOOL IFWL_Edit::Undo(const CFX_ByteStringC& bsRecord) { + return static_cast<CFWL_EditImp*>(GetImpl())->Undo(bsRecord); +} +FX_BOOL IFWL_Edit::Undo() { + return static_cast<CFWL_EditImp*>(GetImpl())->Undo(); +} +FX_BOOL IFWL_Edit::Redo() { + return static_cast<CFWL_EditImp*>(GetImpl())->Redo(); +} +FX_BOOL IFWL_Edit::CanUndo() { + return static_cast<CFWL_EditImp*>(GetImpl())->CanUndo(); +} +FX_BOOL IFWL_Edit::CanRedo() { + return static_cast<CFWL_EditImp*>(GetImpl())->CanRedo(); +} +FWL_ERR IFWL_Edit::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) { + return static_cast<CFWL_EditImp*>(GetImpl()) + ->SetTabWidth(fTabWidth, bEquidistant); +} +FWL_ERR IFWL_Edit::SetOuter(IFWL_Widget* pOuter) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetOuter(pOuter); +} +FWL_ERR IFWL_Edit::SetNumberRange(int32_t iMin, int32_t iMax) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetNumberRange(iMin, iMax); +} +FWL_ERR IFWL_Edit::SetBackColor(FX_DWORD dwColor) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetBackgroundColor(dwColor); +} +FWL_ERR IFWL_Edit::SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetFont(wsFont, fSize); +} +void IFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) { + return static_cast<CFWL_EditImp*>(GetImpl())->SetScrollOffset(fScrollOffset); +} +FX_BOOL IFWL_Edit::GetSuggestWords(CFX_PointF pointf, + std::vector<CFX_ByteString>& sSuggest) { + return static_cast<CFWL_EditImp*>(GetImpl()) + ->GetSuggestWords(pointf, sSuggest); +} +FX_BOOL IFWL_Edit::ReplaceSpellCheckWord(CFX_PointF pointf, + const CFX_ByteStringC& bsReplace) { + return static_cast<CFWL_EditImp*>(GetImpl()) + ->ReplaceSpellCheckWord(pointf, bsReplace); +} +#define FWL_EDIT_Margin 3 +CFWL_EditImp::CFWL_EditImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_fVAlignOffset(0.0f), + m_fScrollOffsetX(0.0f), + m_fScrollOffsetY(0.0f), + m_pEdtEngine(NULL), + m_bLButtonDown(FALSE), + m_nSelStart(0), + m_nLimit(-1), + m_fSpaceAbove(0), + m_fSpaceBelow(0), + m_fFontSize(0), + m_bSetRange(FALSE), + m_iMin(-1), + m_iMax(0xFFFFFFF), + m_backColor(0), + m_updateBackColor(FALSE), + m_iCurRecord(-1), + m_iMaxRecord(128) { + m_rtClient.Reset(); + m_rtEngine.Reset(); + m_rtStatic.Reset(); +} +CFWL_EditImp::~CFWL_EditImp() { + if (m_pEdtEngine) { + m_pEdtEngine->Release(); + m_pEdtEngine = NULL; + } + ClearRecord(); +} +FWL_ERR CFWL_EditImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_Edit; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_EditImp::GetClassID() const { + return FWL_CLASSHASH_Edit; +} +FWL_ERR CFWL_EditImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + if (!m_pDelegate) { + m_pDelegate = new CFWL_EditImpDelegate(this); + } + InitCaret(); + if (!m_pEdtEngine) { + InitEngine(); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::Finalize() { + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + ShowCaret(FALSE); + } + if (m_pHorzScrollBar) { + m_pHorzScrollBar->Finalize(); + } + if (m_pVertScrollBar) { + m_pVertScrollBar->Finalize(); + } + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_EditImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + if (m_pEdtEngine) { + int32_t iTextLen = m_pEdtEngine->GetTextLength(); + if (iTextLen > 0) { + CFX_WideString wsText; + m_pEdtEngine->GetText(wsText, 0); + CFX_SizeF sz = CalcTextSize( + wsText, m_pProperties->m_pThemeProvider, + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine); + rect.Set(0, 0, sz.x, sz.y); + } + } + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { + if (IsShowScrollBar(TRUE)) { + FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( + GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + rect.width += *pfWidth; + rect.width += FWL_EDIT_Margin; + } + if (IsShowScrollBar(FALSE)) { + FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( + GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + rect.height += *pfWidth; + rect.height += FWL_EDIT_Margin; + } + } + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) { + if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { + ShowCaret(FALSE); + } + return CFWL_WidgetImp::SetStates(dwStates, bSet); +} +FWL_ERR CFWL_EditImp::SetWidgetRect(const CFX_RectF& rect) { + return CFWL_WidgetImp::SetWidgetRect(rect); +} +FWL_ERR CFWL_EditImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + Layout(); + if (m_rtClient.IsEmpty()) { + return FWL_ERR_Indefinite; + } + UpdateEditEngine(); + UpdateVAlignment(); + UpdateScroll(); + InitCaret(); + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_EditImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { + if (IsShowScrollBar(TRUE)) { + CFX_RectF rect; + m_pVertScrollBar->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_VScrollBar; + } + } + if (IsShowScrollBar(FALSE)) { + CFX_RectF rect; + m_pHorzScrollBar->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_HScrollBar; + } + } + } + if (m_rtClient.Contains(fx, fy)) { + return FWL_WGTHITTEST_Edit; + } + return FWL_WGTHITTEST_Unknown; +} +#define FX_EDIT_ISLATINWORD(u) \ + (u == 0x2D || (u <= 0x005A && u >= 0x0041) || \ + (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0) || \ + u == 0x0027) +static void AddSquigglyPath(CFX_Path& PathData, + FX_FLOAT fStartX, + FX_FLOAT fEndX, + FX_FLOAT fY, + FX_FLOAT fStep) { + PathData.MoveTo(fStartX, fY); + FX_FLOAT fx; + int32_t i; + for (i = 1, fx = fStartX + fStep; fx < fEndX; fx += fStep, i++) { + PathData.LineTo(fx, fY + (i & 1) * fStep); + } +} +void CFWL_EditImp::AddSpellCheckObj(CFX_Path& PathData, + int32_t nStart, + int32_t nCount, + FX_FLOAT fOffSetX, + FX_FLOAT fOffSetY) { + FX_FLOAT fStartX = 0.0f; + FX_FLOAT fEndX = 0.0f; + FX_FLOAT fY = 0.0f; + FX_FLOAT fStep = 0.0f; + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + CFX_RectFArray rectArray; + CFX_RectF rectText; + const FDE_TXTEDTPARAMS* txtEdtParams = m_pEdtEngine->GetEditParams(); + FX_FLOAT fAsent = (FX_FLOAT)txtEdtParams->pFont->GetAscent() * + txtEdtParams->fFontSize / 1000; + pPage->CalcRangeRectArray(nStart, nCount, rectArray); + for (int i = 0; i < rectArray.GetSize(); i++) { + rectText = rectArray.GetAt(i); + fY = rectText.top + fAsent + fOffSetY; + fStep = txtEdtParams->fFontSize / 16.0f; + fStartX = rectText.left + fOffSetX; + fEndX = fStartX + rectText.Width(); + AddSquigglyPath(PathData, fStartX, fEndX, fY, fStep); + } +} +int32_t CFWL_EditImp::GetWordAtPoint(CFX_PointF pointf, int32_t& nCount) { + return 0; +} +FX_BOOL CFWL_EditImp::GetSuggestWords(CFX_PointF pointf, + std::vector<CFX_ByteString>& sSuggest) { + int32_t nWordCount = 0; + int32_t nWordStart = GetWordAtPoint(pointf, nWordCount); + if (nWordCount < 1) { + return FALSE; + } + CFX_WideString wsSpell; + GetText(wsSpell, nWordStart, nWordCount); + CFX_ByteString sLatinWord; + for (int i = 0; i < nWordCount; i++) { + if (!FX_EDIT_ISLATINWORD(wsSpell[i])) { + break; + } + sLatinWord += (FX_CHAR)wsSpell[i]; + } + if (sLatinWord.IsEmpty()) { + return FALSE; + } + CFWL_EvtEdtCheckWord checkWordEvent; + checkWordEvent.m_pSrcTarget = m_pInterface; + checkWordEvent.bsWord = sLatinWord; + checkWordEvent.bCheckWord = TRUE; + DispatchEvent(&checkWordEvent); + if (checkWordEvent.bCheckWord) { + return FALSE; + } + CFWL_EvtEdtGetSuggestWords suggestWordsEvent; + suggestWordsEvent.m_pSrcTarget = m_pInterface; + suggestWordsEvent.bsWord = sLatinWord; + suggestWordsEvent.bsArraySuggestWords = sSuggest; + suggestWordsEvent.bSuggestWords = FALSE; + DispatchEvent(&checkWordEvent); + return suggestWordsEvent.bSuggestWords; +} +FX_BOOL CFWL_EditImp::ReplaceSpellCheckWord(CFX_PointF pointf, + const CFX_ByteStringC& bsReplace) { + int32_t nWordCount = 0; + int32_t nWordStart = GetWordAtPoint(pointf, nWordCount); + if (nWordCount < 1) { + return FALSE; + } + CFX_WideString wsSpell; + GetText(wsSpell, nWordStart, nWordCount); + for (int i = 0; i < nWordCount; i++) { + if (!FX_EDIT_ISLATINWORD(wsSpell[i])) { + nWordCount = i; + break; + } + } + int32_t nDestLen = bsReplace.GetLength(); + CFX_WideString wsDest; + FX_WCHAR* pBuffer = wsDest.GetBuffer(nDestLen); + for (int32_t i = 0; i < nDestLen; i++) { + pBuffer[i] = bsReplace[i]; + } + wsDest.ReleaseBuffer(nDestLen); + Replace(nWordStart, nWordCount, wsDest); + return TRUE; +} +void CFWL_EditImp::DrawSpellCheck(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + pGraphics->SaveGraphState(); + if (pMatrix) { + pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix)); + } + FX_ARGB cr = 0xFFFF0000; + CFX_Color crLine(cr); + CFWL_EvtEdtCheckWord checkWordEvent; + checkWordEvent.m_pSrcTarget = m_pInterface; + CFX_ByteString sLatinWord; + CFX_Path pathSpell; + pathSpell.Create(); + int32_t nStart = 0; + FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; + FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + CFX_WideString wsSpell; + GetText(wsSpell); + int32_t nContentLen = wsSpell.GetLength(); + for (int i = 0; i < nContentLen; i++) { + if (FX_EDIT_ISLATINWORD(wsSpell[i])) { + if (sLatinWord.IsEmpty()) { + nStart = i; + } + sLatinWord += (FX_CHAR)wsSpell[i]; + } else { + checkWordEvent.bsWord = sLatinWord; + checkWordEvent.bCheckWord = TRUE; + DispatchEvent(&checkWordEvent); + if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) { + AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX, + fOffSetY); + } + sLatinWord.Empty(); + } + } + checkWordEvent.bsWord = sLatinWord; + checkWordEvent.bCheckWord = TRUE; + DispatchEvent(&checkWordEvent); + if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) { + AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX, + fOffSetY); + } + if (!pathSpell.IsEmpty()) { + CFX_RectF rtClip = m_rtEngine; + CFX_Matrix mt; + mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY); + if (pMatrix) { + pMatrix->TransformRect(rtClip); + mt.Concat(*pMatrix); + } + pGraphics->SetClipRect(rtClip); + pGraphics->SetStrokeColor(&crLine); + pGraphics->SetLineWidth(0); + pGraphics->StrokePath(&pathSpell, NULL); + } + pGraphics->RestoreGraphState(); +} +FWL_ERR CFWL_EditImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + if (m_rtClient.IsEmpty()) { + return FWL_ERR_Indefinite; + } + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (!m_pWidgetMgr->IsFormDisabled()) { + DrawTextBk(pGraphics, pTheme, pMatrix); + } + if (m_pEdtEngine) { + DrawContent(pGraphics, pTheme, pMatrix); + } + if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && + !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) { + DrawSpellCheck(pGraphics, pMatrix); + } + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_EDT_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_EDT_Edge, pTheme, pMatrix); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { + if (!pThemeProvider) + return FWL_ERR_Indefinite; + if (m_pHorzScrollBar) { + m_pHorzScrollBar->SetThemeProvider(pThemeProvider); + } + if (m_pVertScrollBar) { + m_pVertScrollBar->SetThemeProvider(pThemeProvider); + } + if (m_pCaret) { + m_pCaret->SetThemeProvider(pThemeProvider); + } + m_pProperties->m_pThemeProvider = pThemeProvider; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetText(const CFX_WideString& wsText) { + m_pEdtEngine->SetText(wsText); + return FWL_ERR_Succeeded; +} +int32_t CFWL_EditImp::GetTextLength() const { + if (!m_pEdtEngine) + return -1; + return m_pEdtEngine->GetTextLength(); +} +FWL_ERR CFWL_EditImp::GetText(CFX_WideString& wsText, + int32_t nStart, + int32_t nCount) const { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->GetText(wsText, nStart, nCount); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::ClearText() { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->ClearText(); + return FWL_ERR_Succeeded; +} +int32_t CFWL_EditImp::GetCaretPos() const { + if (!m_pEdtEngine) + return -1; + return m_pEdtEngine->GetCaretPos(); +} +int32_t CFWL_EditImp::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) { + if (!m_pEdtEngine) + return -1; + return m_pEdtEngine->SetCaretPos(nIndex, bBefore); +} +FWL_ERR CFWL_EditImp::AddSelRange(int32_t nStart, int32_t nCount) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->AddSelRange(nStart, nCount); + return FWL_ERR_Succeeded; +} +int32_t CFWL_EditImp::CountSelRanges() { + if (!m_pEdtEngine) + return 0; + return m_pEdtEngine->CountSelRanges(); + return FWL_ERR_Succeeded; +} +int32_t CFWL_EditImp::GetSelRange(int32_t nIndex, int32_t& nStart) { + if (!m_pEdtEngine) + return -1; + return m_pEdtEngine->GetSelRange(nIndex, nStart); +} +FWL_ERR CFWL_EditImp::ClearSelections() { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->ClearSelection(); + return FWL_ERR_Succeeded; +} +int32_t CFWL_EditImp::GetLimit() { + return m_nLimit; +} +FWL_ERR CFWL_EditImp::SetLimit(int32_t nLimit) { + m_nLimit = nLimit; + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->SetLimit(nLimit); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetAliasChar(FX_WCHAR wAlias) { + if (!m_pEdtEngine) + return FWL_ERR_Indefinite; + m_pEdtEngine->SetAliasChar(wAlias); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::Insert(int32_t nStart, + const FX_WCHAR* lpText, + int32_t nLen) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { + return FWL_ERR_Indefinite; + } + m_pEdtEngine->Insert(nStart, lpText, nLen); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::DeleteSelections() { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + int32_t iCount = m_pEdtEngine->CountSelRanges(); + if (iCount > 0) { + m_pEdtEngine->Delete(-1); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::DeleteRange(int32_t nStart, int32_t nCount) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->DeleteRange(nStart, nCount); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::ReplaceSelections(const CFX_WideStringC& wsReplace) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + int32_t iCount = m_pEdtEngine->CountSelRanges(); + for (int i = 0; i < iCount; i++) { + int32_t nStart; + int32_t nCount = m_pEdtEngine->GetSelRange(i, nStart); + m_pEdtEngine->Replace(nStart, nCount, wsReplace); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::Replace(int32_t nStart, + int32_t nLen, + const CFX_WideStringC& wsReplace) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + m_pEdtEngine->Replace(nStart, nLen, wsReplace); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::DoClipboard(int32_t iCmd) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { + return FWL_ERR_Succeeded; + } + return FWL_ERR_Indefinite; +} +FX_BOOL CFWL_EditImp::Copy(CFX_WideString& wsCopy) { + if (!m_pEdtEngine) + return FALSE; + int32_t nCount = m_pEdtEngine->CountSelRanges(); + if (nCount == 0) { + return FALSE; + } + wsCopy.Empty(); + CFX_WideString wsTemp; + int32_t nStart, nLength; + for (int32_t i = 0; i < nCount; i++) { + nLength = m_pEdtEngine->GetSelRange(i, nStart); + m_pEdtEngine->GetText(wsTemp, nStart, nLength); + wsCopy += wsTemp; + wsTemp.Empty(); + } + return TRUE; +} +FX_BOOL CFWL_EditImp::Cut(CFX_WideString& wsCut) { + if (!m_pEdtEngine) + return FALSE; + int32_t nCount = m_pEdtEngine->CountSelRanges(); + if (nCount == 0) { + return FALSE; + } + wsCut.Empty(); + CFX_WideString wsTemp; + int32_t nStart, nLength; + for (int32_t i = 0; i < nCount; i++) { + nLength = m_pEdtEngine->GetSelRange(i, nStart); + m_pEdtEngine->GetText(wsTemp, nStart, nLength); + wsCut += wsTemp; + wsTemp.Empty(); + } + m_pEdtEngine->Delete(0); + return TRUE; +} +FX_BOOL CFWL_EditImp::Paste(const CFX_WideString& wsPaste) { + if (!m_pEdtEngine) + return FALSE; + int32_t nCaret = m_pEdtEngine->GetCaretPos(); + int32_t iError = + m_pEdtEngine->Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength()); + if (iError < 0) { + ProcessInsertError(iError); + return FALSE; + } + return TRUE; +} +FX_BOOL CFWL_EditImp::Delete() { + if (!m_pEdtEngine) + return FALSE; + int32_t nCount = m_pEdtEngine->CountSelRanges(); + if (nCount < 1) { + return FALSE; + } + m_pEdtEngine->Delete(0); + return TRUE; +} +FX_BOOL CFWL_EditImp::Redo(const CFX_ByteStringC& bsRecord) { + if (!m_pEdtEngine) + return FALSE; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) { + return TRUE; + } + return m_pEdtEngine->Redo(bsRecord); +} +FX_BOOL CFWL_EditImp::Undo(const CFX_ByteStringC& bsRecord) { + if (!m_pEdtEngine) + return FALSE; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) { + return TRUE; + } + return m_pEdtEngine->Undo(bsRecord); +} +FX_BOOL CFWL_EditImp::Undo() { + if (!CanUndo()) { + return FALSE; + } + CFX_ByteString bsRecord = m_RecordArr[m_iCurRecord--]; + return Undo(bsRecord); +} +FX_BOOL CFWL_EditImp::Redo() { + if (!CanRedo()) { + return FALSE; + } + CFX_ByteString bsRecord = m_RecordArr[++m_iCurRecord]; + return Redo(bsRecord); +} +FX_BOOL CFWL_EditImp::CanUndo() { + return m_iCurRecord >= 0; +} +FX_BOOL CFWL_EditImp::CanRedo() { + return m_iCurRecord < m_RecordArr.GetSize() - 1; +} +FWL_ERR CFWL_EditImp::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) { + if (!m_pEdtEngine) + return FWL_ERR_Succeeded; + FDE_LPTXTEDTPARAMS pParams = + (FDE_LPTXTEDTPARAMS)m_pEdtEngine->GetEditParams(); + pParams->fTabWidth = fTabWidth; + pParams->bTabEquidistant = bEquidistant; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetOuter(IFWL_Widget* pOuter) { + m_pOuter = pOuter; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetNumberRange(int32_t iMin, int32_t iMax) { + m_iMin = iMin; + m_iMax = iMax; + m_bSetRange = TRUE; + return FWL_ERR_Succeeded; +} +void CFWL_EditImp::On_CaretChanged(IFDE_TxtEdtEngine* pEdit, + int32_t nPage, + FX_BOOL bVisible) { + if (m_rtEngine.IsEmpty()) { + return; + } + if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + return; + } + FX_BOOL bRepaintContent = UpdateOffset(); + UpdateCaret(); + CFX_RectF rtInvalid; + rtInvalid.Set(0, 0, 0, 0); + FX_BOOL bRepaintScroll = FALSE; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { + IFWL_ScrollBar* pScroll = UpdateScroll(); + if (pScroll) { + pScroll->GetWidgetRect(rtInvalid); + bRepaintScroll = TRUE; + } + } + if (bRepaintContent || bRepaintScroll) { + if (bRepaintContent) { + rtInvalid.Union(m_rtEngine); + } + Repaint(&rtInvalid); + } +} +void CFWL_EditImp::On_TextChanged(IFDE_TxtEdtEngine* pEdit, + FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) { + FX_DWORD dwStyleEx = m_pProperties->m_dwStyleExes; + if (dwStyleEx & FWL_STYLEEXT_EDT_VAlignMask) { + UpdateVAlignment(); + } + IFDE_TxtEdtPage* page = m_pEdtEngine->GetPage(0); + FX_FLOAT fContentWidth = page->GetContentsBox().width; + FX_FLOAT fContentHeight = page->GetContentsBox().height; + CFX_RectF rtTemp; + GetClientRect(rtTemp); + FX_BOOL bHSelfAdaption = + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption; + FX_BOOL bVSelfAdaption = + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption; + FX_BOOL bNeedUpdate = FALSE; + if (bHSelfAdaption || bVSelfAdaption) { + CFWL_EvtEdtPreSelfAdaption evt; + evt.m_pSrcTarget = m_pInterface; + evt.bHSelfAdaption = TRUE; + evt.bVSelfAdaption = TRUE; + FX_FLOAT fWidth; + FX_FLOAT fHight; + fWidth = bHSelfAdaption ? fContentWidth : m_pProperties->m_rtWidget.width; + fHight = bVSelfAdaption ? fContentHeight : m_pProperties->m_rtWidget.height; + evt.rtAfterChange.Set(0, 0, fWidth, fHight); + DispatchEvent(&evt); + if (!evt.bHSelfAdaption) { + ModifyStylesEx( + 0, FWL_STYLEEXT_EDT_HSelfAdaption | FWL_STYLEEXT_EDT_AutoHScroll); + } + if (!evt.bVSelfAdaption) { + ModifyStylesEx( + 0, FWL_STYLEEXT_EDT_VSelfAdaption | FWL_STYLEEXT_EDT_AutoVScroll); + } + bNeedUpdate = (bHSelfAdaption && !evt.bHSelfAdaption) || + (bVSelfAdaption && !evt.bVSelfAdaption); + } + FX_FLOAT fContentWidth1 = fContentWidth; + FX_FLOAT fContentHeight1 = fContentHeight; + if (bNeedUpdate) { + UpdateEditParams(); + UpdateEditLayout(); + IFDE_TxtEdtPage* page1 = m_pEdtEngine->GetPage(0); + fContentWidth1 = page1->GetContentsBox().width; + fContentHeight1 = page1->GetContentsBox().height; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption) { + rtTemp.width = std::max(m_pProperties->m_rtWidget.width, fContentWidth1); + m_pProperties->m_rtWidget.width = fContentWidth1; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption) { + rtTemp.height = std::max(m_pProperties->m_rtWidget.height, fContentHeight1); + m_pProperties->m_rtWidget.height = fContentHeight1; + } + CFWL_EvtEdtTextChanged event; + event.m_pSrcTarget = m_pInterface; + event.nChangeType = ChangeInfo.nChangeType; + event.wsInsert = ChangeInfo.wsInsert; + event.wsDelete = ChangeInfo.wsDelete; + event.wsPrevText = ChangeInfo.wsPrevText; + DispatchEvent(&event); + LayoutScrollBar(); + Repaint(&rtTemp); +} +void CFWL_EditImp::On_SelChanged(IFDE_TxtEdtEngine* pEdit) { + CFX_RectF rtTemp; + GetClientRect(rtTemp); + Repaint(&rtTemp); +} +FX_BOOL CFWL_EditImp::On_PageLoad(IFDE_TxtEdtEngine* pEdit, + int32_t nPageIndex, + int32_t nPurpose) { + IFDE_TxtEdtEngine* pEdtEngine = m_pEdtEngine; + IFDE_TxtEdtPage* pPage = pEdtEngine->GetPage(nPageIndex); + if (!pPage) + return FALSE; + pPage->LoadPage(nullptr, nullptr); + return TRUE; +} +FX_BOOL CFWL_EditImp::On_PageUnload(IFDE_TxtEdtEngine* pEdit, + int32_t nPageIndex, + int32_t nPurpose) { + IFDE_TxtEdtEngine* pEdtEngine = m_pEdtEngine; + IFDE_TxtEdtPage* pPage = pEdtEngine->GetPage(nPageIndex); + if (!pPage) + return FALSE; + pPage->UnloadPage(nullptr); + return TRUE; +} + +void CFWL_EditImp::On_AddDoRecord(IFDE_TxtEdtEngine* pEdit, + const CFX_ByteStringC& bsDoRecord) { + AddDoRecord(bsDoRecord); +} + +FX_BOOL CFWL_EditImp::On_ValidateField(IFDE_TxtEdtEngine* pEdit, + int32_t nBlockIndex, + int32_t nFieldIndex, + const CFX_WideString& wsFieldText, + int32_t nCharIndex) { + return TRUE; +} +FX_BOOL CFWL_EditImp::On_ValidateBlock(IFDE_TxtEdtEngine* pEdit, + int32_t nBlockIndex) { + return TRUE; +} +FX_BOOL CFWL_EditImp::On_GetBlockFormatText(IFDE_TxtEdtEngine* pEdit, + int32_t nBlockIndex, + CFX_WideString& wsBlockText) { + return FALSE; +} +FX_BOOL CFWL_EditImp::On_Validate(IFDE_TxtEdtEngine* pEdit, + CFX_WideString& wsText) { + IFWL_Widget* pDst = GetOuter(); + if (!pDst) { + pDst = m_pInterface; + } + CFWL_EvtEdtValidate event; + event.pDstWidget = pDst; + event.m_pSrcTarget = m_pInterface; + event.wsInsert = wsText; + event.bValidate = TRUE; + DispatchEvent(&event); + return event.bValidate; +} +FWL_ERR CFWL_EditImp::SetBackgroundColor(FX_DWORD color) { + m_backColor = color; + m_updateBackColor = TRUE; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImp::SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize) { + m_wsFont = wsFont; + m_fFontSize = fSize; + return FWL_ERR_Succeeded; +} +void CFWL_EditImp::SetScrollOffset(FX_FLOAT fScrollOffset) { + m_fScrollOffsetY = fScrollOffset; +} +void CFWL_EditImp::DrawTextBk(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_EDT_Background; + param.m_dwData = FWL_PARTDATA_EDT_Background; + param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly + ? FWL_PARTSTATE_EDT_ReadOnly + : FWL_PARTSTATE_EDT_Normal; + FX_DWORD dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled); + if (dwStates) { + param.m_dwStates = FWL_PARTSTATE_EDT_Disable; + } + param.m_pGraphics = pGraphics; + param.m_matrix = *pMatrix; + param.m_rtPart = m_rtClient; + pTheme->DrawBackground(¶m); + if (!IsShowScrollBar(TRUE) || !IsShowScrollBar(FALSE)) { + return; + } + CFX_RectF rtScorll; + m_pHorzScrollBar->GetWidgetRect(rtScorll); + CFX_RectF rtStatic; + rtStatic.Set(m_rtClient.right() - rtScorll.height, + m_rtClient.bottom() - rtScorll.height, rtScorll.height, + rtScorll.height); + param.m_dwData = FWL_PARTDATA_EDT_StaticBackground; + param.m_rtPart = rtStatic; + pTheme->DrawBackground(¶m); +} +void CFWL_EditImp::DrawContent(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (!m_pEdtEngine) + return; + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + if (!pPage) + return; + pGraphics->SaveGraphState(); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { + pGraphics->SaveGraphState(); + } + CFX_RectF rtClip = m_rtEngine; + FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; + FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + CFX_Matrix mt; + mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY); + if (pMatrix) { + pMatrix->TransformRect(rtClip); + mt.Concat(*pMatrix); + } + FX_BOOL bShowSel = + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); + if (bShowSel) { + IFWL_Widget* pForm = + m_pWidgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_SystemForm); + if (pForm) { + bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) != + FWL_WGTSTATE_Deactivated; + } + } + int32_t nSelCount = m_pEdtEngine->CountSelRanges(); + if (bShowSel && nSelCount > 0) { + int32_t nPageCharStart = pPage->GetCharStart(); + int32_t nPageCharCount = pPage->GetCharCount(); + int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1; + int32_t nCharCount; + int32_t nCharStart; + CFX_RectFArray rectArr; + int32_t i = 0; + for (i = 0; i < nSelCount; i++) { + nCharCount = m_pEdtEngine->GetSelRange(i, nCharStart); + int32_t nCharEnd = nCharStart + nCharCount - 1; + if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) { + continue; + } + int32_t nBgn = std::max(nCharStart, nPageCharStart); + int32_t nEnd = std::min(nCharEnd, nPageCharEnd); + pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1, + rectArr); + } + int32_t nCount = rectArr.GetSize(); + CFX_Path path; + path.Create(); + for (i = 0; i < nCount; i++) { + rectArr[i].left += fOffSetX; + rectArr[i].top += fOffSetY; + path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width, + rectArr[i].height); + } + pGraphics->SetClipRect(rtClip); + CFWL_ThemeBackground param; + param.m_pGraphics = pGraphics; + param.m_matrix = *pMatrix; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_EDT_Background; + param.m_pPath = &path; + pTheme->DrawBackground(¶m); + } + CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice(); + if (!pRenderDev) + return; + IFDE_RenderDevice* pRenderDevice = IFDE_RenderDevice::Create(pRenderDev); + if (!pRenderDevice) + return; + IFDE_RenderContext* pRenderContext = IFDE_RenderContext::Create(); + if (!pRenderContext) + return; + pRenderDevice->SetClipRect(rtClip); + pRenderContext->StartRender(pRenderDevice, pPage, mt); + pRenderContext->DoRender(NULL); + pRenderContext->Release(); + pRenderDevice->Release(); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { + pGraphics->RestoreGraphState(); + CFX_Path path; + path.Create(); + int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1; + FX_FLOAT fStep = m_rtEngine.width / iLimit; + FX_FLOAT fLeft = m_rtEngine.left + 1; + for (int32_t i = 1; i < iLimit; i++) { + fLeft += fStep; + path.AddLine(fLeft, m_rtClient.top, fLeft, m_rtClient.bottom()); + } + CFWL_ThemeBackground param; + param.m_pGraphics = pGraphics; + param.m_matrix = *pMatrix; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_EDT_CombTextLine; + param.m_pPath = &path; + pTheme->DrawBackground(¶m); + } + pGraphics->RestoreGraphState(); +} +void CFWL_EditImp::UpdateEditEngine() { + UpdateEditParams(); + UpdateEditLayout(); + if (m_nLimit > -1) { + m_pEdtEngine->SetLimit(m_nLimit); + } +} +void CFWL_EditImp::UpdateEditParams() { + FDE_TXTEDTPARAMS params; + params.nHorzScale = 100; + params.fPlateWidth = m_rtEngine.width; + params.fPlateHeight = m_rtEngine.height; + if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) { + params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) { + params.dwMode |= FDE_TEXTEDITMODE_Validate; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) { + params.dwMode |= FDE_TEXTEDITMODE_Password; + } + switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) { + case FWL_STYLEEXT_EDT_HNear: { + params.dwAlignment |= FDE_TEXTEDITALIGN_Left; + break; + } + case FWL_STYLEEXT_EDT_HCenter: { + params.dwAlignment |= FDE_TEXTEDITALIGN_Center; + break; + } + case FWL_STYLEEXT_EDT_HFar: { + params.dwAlignment |= FDE_TEXTEDITALIGN_Right; + break; + } + default: {} + } + switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) { + case FWL_STYLEEXT_EDT_Justified: { + params.dwAlignment |= FDE_TEXTEDITALIGN_Justified; + break; + } + case FWL_STYLEEXT_EDT_Distributed: { + params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed; + break; + } + default: { params.dwAlignment |= FDE_TEXTEDITALIGN_Normal; } + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { + params.dwMode |= FDE_TEXTEDITMODE_MultiLines; + if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) { + params.dwMode |= + FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz; + } + if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) { + params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert; + } else { + params.fPlateHeight = 0x00FFFFFF; + } + } else { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) { + params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz; + } + } + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { + params.dwMode |= FDE_TEXTEDITMODE_ReadOnly; + } + FX_FLOAT* pFontSize = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FontSize)); + if (!pFontSize) + return; + m_fFontSize = *pFontSize; + FX_DWORD* pFontColor = + static_cast<FX_DWORD*>(GetThemeCapacity(FWL_WGTCAPACITY_TextColor)); + if (!pFontColor) + return; + params.dwFontColor = *pFontColor; + FX_FLOAT* pLineHeight = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_LineHeight)); + if (!pLineHeight) + return; + params.fLineSpace = *pLineHeight; + IFX_Font* pFont = + static_cast<IFX_Font*>(GetThemeCapacity(FWL_WGTCAPACITY_Font)); + if (!pFont) + return; + params.pFont = pFont; + params.fFontSize = m_fFontSize; + params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace); + if (params.nLineCount <= 0) { + params.nLineCount = 1; + } + params.fTabWidth = params.fFontSize * 1; + params.bTabEquidistant = TRUE; + params.wLineBreakChar = L'\n'; + params.nCharRotation = 0; + params.pEventSink = this; + m_pEdtEngine->SetEditParams(params); +} + +void CFWL_EditImp::UpdateEditLayout() { + if (m_pEdtEngine->GetTextLength() <= 0) + m_pEdtEngine->SetTextByStream(nullptr); + + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + if (pPage) + pPage->UnloadPage(nullptr); + + m_pEdtEngine->StartLayout(); + m_pEdtEngine->DoLayout(nullptr); + m_pEdtEngine->EndLayout(); + pPage = m_pEdtEngine->GetPage(0); + if (pPage) + pPage->LoadPage(nullptr, nullptr); +} + +FX_BOOL CFWL_EditImp::UpdateOffset() { + CFX_RectF rtCaret; + m_pEdtEngine->GetCaretRect(rtCaret); + FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; + FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; + rtCaret.Offset(fOffSetX, fOffSetY); + const CFX_RectF& rtEidt = m_rtEngine; + if (rtEidt.Contains(rtCaret)) { + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + if (!pPage) + return FALSE; + CFX_RectF rtFDE = pPage->GetContentsBox(); + rtFDE.Offset(fOffSetX, fOffSetY); + if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) { + m_fScrollOffsetX += rtFDE.right() - rtEidt.right(); + if (m_fScrollOffsetX < 0) { + m_fScrollOffsetX = 0; + } + } + if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) { + m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom(); + if (m_fScrollOffsetY < 0) { + m_fScrollOffsetY = 0; + } + } + return FALSE; + } else { + FX_FLOAT offsetX = 0.0; + FX_FLOAT offsetY = 0.0; + if (rtCaret.left < rtEidt.left) { + offsetX = rtCaret.left - rtEidt.left; + } + if (rtCaret.right() > rtEidt.right()) { + offsetX = rtCaret.right() - rtEidt.right(); + } + if (rtCaret.top < rtEidt.top) { + offsetY = rtCaret.top - rtEidt.top; + } + if (rtCaret.bottom() > rtEidt.bottom()) { + offsetY = rtCaret.bottom() - rtEidt.bottom(); + } + if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption)) { + m_fScrollOffsetX += offsetX; + } + if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption)) { + m_fScrollOffsetY += offsetY; + } + if (m_fFontSize > m_rtEngine.height) { + m_fScrollOffsetY = 0; + } + return TRUE; + } +} +FX_BOOL CFWL_EditImp::UpdateOffset(IFWL_ScrollBar* pScrollBar, + FX_FLOAT fPosChanged) { + if (pScrollBar == m_pHorzScrollBar.get()) { + m_fScrollOffsetX += fPosChanged; + } else { + m_fScrollOffsetY += fPosChanged; + } + return TRUE; +} +void CFWL_EditImp::UpdateVAlignment() { + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + if (!pPage) + return; + const CFX_RectF& rtFDE = pPage->GetContentsBox(); + FX_FLOAT fOffsetY = 0.0f; + FX_FLOAT fSpaceAbove = 0.0f; + FX_FLOAT fSpaceBelow = 0.0f; + CFX_SizeF* pSpace = static_cast<CFX_SizeF*>( + GetThemeCapacity(FWL_WGTCAPACITY_SpaceAboveBelow)); + if (pSpace) { + fSpaceAbove = pSpace->x; + fSpaceBelow = pSpace->y; + } + if (fSpaceAbove < 0.1f) { + fSpaceAbove = 0; + } + if (fSpaceBelow < 0.1f) { + fSpaceBelow = 0; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) { + fOffsetY = (m_rtEngine.height - rtFDE.height) / 2; + if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 && + fSpaceAbove < fSpaceBelow) { + return; + } + fOffsetY += (fSpaceAbove - fSpaceBelow) / 2; + } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) { + fOffsetY = (m_rtEngine.height - rtFDE.height); + fOffsetY -= fSpaceBelow; + } else { + fOffsetY += fSpaceAbove; + } + m_fVAlignOffset = fOffsetY; + if (m_fVAlignOffset < 0) { + m_fVAlignOffset = 0; + } +} +void CFWL_EditImp::UpdateCaret() { + CFX_RectF rtFDE; + m_pEdtEngine->GetCaretRect(rtFDE); + rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX, + m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); + CFX_RectF rtCaret; + rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height); + CFX_RectF temp = rtCaret; + CFX_RectF rtClient; + GetClientRect(rtClient); + rtCaret.Intersect(rtClient); + if (rtCaret.left > rtClient.right()) { + FX_FLOAT right = rtCaret.right(); + rtCaret.left = rtClient.right() - 1; + rtCaret.width = right - rtCaret.left; + } + FX_BOOL bIntersect = !rtCaret.IsEmpty(); + FX_BOOL bShow = TRUE; + FX_BOOL bShowWhole = FALSE; + if (!(m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) || !bIntersect) { + bShow = FALSE; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption && + temp.right() > m_rtEngine.right()) { + bShowWhole = TRUE; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption && + temp.bottom() > m_rtEngine.bottom()) { + bShowWhole = TRUE; + } else { + bShow = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && bIntersect); + } + if (bShowWhole) { + rtCaret = temp; + } + ShowCaret(bShow, &rtCaret); +} +IFWL_ScrollBar* CFWL_EditImp::UpdateScroll() { + FX_BOOL bShowHorz = + m_pHorzScrollBar && + ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0); + FX_BOOL bShowVert = + m_pVertScrollBar && + ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0); + if (!bShowHorz && !bShowVert) { + return NULL; + } + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + if (!pPage) + return NULL; + const CFX_RectF& rtFDE = pPage->GetContentsBox(); + IFWL_ScrollBar* pRepaint = NULL; + if (bShowHorz) { + CFX_RectF rtScroll; + m_pHorzScrollBar->GetWidgetRect(rtScroll); + if (rtScroll.width < rtFDE.width) { + m_pHorzScrollBar->LockUpdate(); + FX_FLOAT fRange = rtFDE.width - rtScroll.width; + m_pHorzScrollBar->SetRange(0.0f, fRange); + FX_FLOAT fPos = m_fScrollOffsetX; + if (fPos < 0.0f) { + fPos = 0.0f; + } + if (fPos > fRange) { + fPos = fRange; + } + m_pHorzScrollBar->SetPos(fPos); + m_pHorzScrollBar->SetTrackPos(fPos); + m_pHorzScrollBar->SetPageSize(rtScroll.width); + m_pHorzScrollBar->SetStepSize(rtScroll.width / 10); + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, FALSE); + m_pHorzScrollBar->UnlockUpdate(); + m_pHorzScrollBar->Update(); + pRepaint = m_pHorzScrollBar.get(); + } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) { + m_pHorzScrollBar->LockUpdate(); + m_pHorzScrollBar->SetRange(0, -1); + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, TRUE); + m_pHorzScrollBar->UnlockUpdate(); + m_pHorzScrollBar->Update(); + pRepaint = m_pHorzScrollBar.get(); + } + } + if (bShowVert) { + CFX_RectF rtScroll; + m_pVertScrollBar->GetWidgetRect(rtScroll); + if (rtScroll.height < rtFDE.height) { + m_pVertScrollBar->LockUpdate(); + FX_FLOAT fStep = m_pEdtEngine->GetEditParams()->fLineSpace; + FX_FLOAT fRange = rtFDE.height - m_rtEngine.height; + if (fRange < fStep) { + fRange = fStep; + } + m_pVertScrollBar->SetRange(0.0f, fRange); + FX_FLOAT fPos = m_fScrollOffsetY; + if (fPos < 0.0f) { + fPos = 0.0f; + } + if (fPos > fRange) { + fPos = fRange; + } + m_pVertScrollBar->SetPos(fPos); + m_pVertScrollBar->SetTrackPos(fPos); + m_pVertScrollBar->SetPageSize(rtScroll.height); + m_pVertScrollBar->SetStepSize(fStep); + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, FALSE); + m_pVertScrollBar->UnlockUpdate(); + m_pVertScrollBar->Update(); + pRepaint = m_pVertScrollBar.get(); + } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) { + m_pVertScrollBar->LockUpdate(); + m_pVertScrollBar->SetRange(0, -1); + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, TRUE); + m_pVertScrollBar->UnlockUpdate(); + m_pVertScrollBar->Update(); + pRepaint = m_pVertScrollBar.get(); + } + } + return pRepaint; +} +FX_BOOL CFWL_EditImp::IsShowScrollBar(FX_BOOL bVert) { + FX_BOOL bShow = + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) + ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == + FWL_WGTSTATE_Focused + : TRUE; + if (bVert) { + return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) && + IsContentHeightOverflow(); + } + return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine); +} +FX_BOOL CFWL_EditImp::IsContentHeightOverflow() { + if (!m_pEdtEngine) + return FALSE; + IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0); + if (!pPage) + return FALSE; + return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f; +} +int32_t CFWL_EditImp::AddDoRecord(const CFX_ByteStringC& bsDoRecord) { + int32_t nCount = m_RecordArr.GetSize(); + if (m_iCurRecord == nCount - 1) { + if (nCount == m_iMaxRecord) { + m_RecordArr.RemoveAt(0); + m_iCurRecord--; + } + } else { + for (int32_t i = nCount - 1; i > m_iCurRecord; i--) { + m_RecordArr.RemoveAt(i); + } + } + m_RecordArr.Add(bsDoRecord); + return m_iCurRecord = m_RecordArr.GetSize() - 1; +} +void CFWL_EditImp::Layout() { + GetClientRect(m_rtClient); + m_rtEngine = m_rtClient; + FX_FLOAT* pfWidth = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pfWidth) + return; + FX_FLOAT fWidth = *pfWidth; + if (!m_pOuter) { + CFX_RectF* pUIMargin = + static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin)); + if (pUIMargin) { + m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, + pUIMargin->height); + } + } else if (m_pOuter->GetClassID() == FWL_CLASSHASH_DateTimePicker) { + CFWL_ThemePart part; + part.m_pWidget = m_pOuter; + CFX_RectF* pUIMargin = + static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity( + &part, FWL_WGTCAPACITY_UIMargin)); + if (pUIMargin) { + m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, + pUIMargin->height); + } + } + FX_BOOL bShowVertScrollbar = IsShowScrollBar(TRUE); + FX_BOOL bShowHorzScrollbar = IsShowScrollBar(FALSE); + if (bShowVertScrollbar) { + InitScrollBar(); + CFX_RectF rtVertScr; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { + rtVertScr.Set(m_rtClient.right() + FWL_EDIT_Margin, m_rtClient.top, + fWidth, m_rtClient.height); + } else { + rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth, + m_rtClient.height); + if (bShowHorzScrollbar) { + rtVertScr.height -= fWidth; + } + m_rtEngine.width -= fWidth; + } + m_pVertScrollBar->SetWidgetRect(rtVertScr); + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); + m_pVertScrollBar->Update(); + } else if (m_pVertScrollBar) { + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } + if (bShowHorzScrollbar) { + InitScrollBar(FALSE); + CFX_RectF rtHoriScr; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { + rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + FWL_EDIT_Margin, + m_rtClient.width, fWidth); + } else { + rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth, + m_rtClient.width, fWidth); + if (bShowVertScrollbar) { + rtHoriScr.width -= fWidth; + } + m_rtEngine.height -= fWidth; + } + m_pHorzScrollBar->SetWidgetRect(rtHoriScr); + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); + m_pHorzScrollBar->Update(); + } else if (m_pHorzScrollBar) { + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } +} +void CFWL_EditImp::LayoutScrollBar() { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) == + 0) { + return; + } + FX_FLOAT* pfWidth = NULL; + FX_BOOL bShowVertScrollbar = IsShowScrollBar(TRUE); + FX_BOOL bShowHorzScrollbar = IsShowScrollBar(FALSE); + if (bShowVertScrollbar) { + if (!m_pVertScrollBar) { + pfWidth = static_cast<FX_FLOAT*>( + GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + FX_FLOAT fWidth = pfWidth ? *pfWidth : 0; + InitScrollBar(); + CFX_RectF rtVertScr; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { + rtVertScr.Set(m_rtClient.right() + FWL_EDIT_Margin, m_rtClient.top, + fWidth, m_rtClient.height); + } else { + rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth, + m_rtClient.height); + if (bShowHorzScrollbar) { + rtVertScr.height -= fWidth; + } + } + m_pVertScrollBar->SetWidgetRect(rtVertScr); + m_pVertScrollBar->Update(); + } + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); + } else if (m_pVertScrollBar) { + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } + if (bShowHorzScrollbar) { + if (!m_pHorzScrollBar) { + if (!pfWidth) { + pfWidth = static_cast<FX_FLOAT*>( + GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + } + FX_FLOAT fWidth = pfWidth ? *pfWidth : 0; + InitScrollBar(FALSE); + CFX_RectF rtHoriScr; + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { + rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + FWL_EDIT_Margin, + m_rtClient.width, fWidth); + } else { + rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth, + m_rtClient.width, fWidth); + if (bShowVertScrollbar) { + rtHoriScr.width -= (fWidth); + } + } + m_pHorzScrollBar->SetWidgetRect(rtHoriScr); + m_pHorzScrollBar->Update(); + } + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); + } else if (m_pHorzScrollBar) { + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } + if (bShowVertScrollbar || bShowHorzScrollbar) { + UpdateScroll(); + } +} +void CFWL_EditImp::DeviceToEngine(CFX_PointF& pt) { + pt.x += -m_rtEngine.left + m_fScrollOffsetX; + pt.y += -m_rtEngine.top - m_fVAlignOffset + m_fScrollOffsetY; +} +void CFWL_EditImp::InitScrollBar(FX_BOOL bVert) { + if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) { + return; + } + CFWL_WidgetImpProperties prop; + prop.m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz; + prop.m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible; + prop.m_pParent = m_pInterface; + prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; + IFWL_ScrollBar* pScrollBar = IFWL_ScrollBar::Create(prop, m_pInterface); + pScrollBar->Initialize(); + (bVert ? &m_pVertScrollBar : &m_pHorzScrollBar)->reset(pScrollBar); +} +void CFWL_EditImp::InitEngine() { + if (m_pEdtEngine) { + return; + } + m_pEdtEngine = IFDE_TxtEdtEngine::Create(); +} +extern FX_BOOL FWL_ShowCaret(IFWL_Widget* pWidget, + FX_BOOL bVisible, + const CFX_RectF* pRtAnchor); +void CFWL_EditImp::ShowCaret(FX_BOOL bVisible, CFX_RectF* pRect) { + if (m_pCaret) { + m_pCaret->ShowCaret(bVisible); + if (bVisible && !pRect->IsEmpty()) { + m_pCaret->SetWidgetRect(*pRect); + } + Repaint(&m_rtEngine); + } else { + IFWL_Widget* pOuter = m_pInterface; + if (bVisible) { + pRect->Offset(m_pProperties->m_rtWidget.left, + m_pProperties->m_rtWidget.top); + } + while (pOuter->GetOuter()) { + pOuter = pOuter->GetOuter(); + if (bVisible) { + CFX_RectF rtOuter; + pOuter->GetWidgetRect(rtOuter); + pRect->Offset(rtOuter.left, rtOuter.top); + } + } + FWL_ShowCaret(pOuter, bVisible, pRect); + } +} +FX_BOOL CFWL_EditImp::ValidateNumberChar(FX_WCHAR cNum) { + if (!m_pEdtEngine) { + return FALSE; + } + if (!m_bSetRange) { + return TRUE; + } + CFX_WideString wsOld, wsText; + m_pEdtEngine->GetText(wsText, 0); + if (wsText.IsEmpty()) { + if (cNum == L'0') { + return FALSE; + } + return TRUE; + } + int32_t caretPos = m_pEdtEngine->GetCaretPos(); + int32_t iSel = CountSelRanges(); + if (iSel == 0) { + if (cNum == L'0' && caretPos == 0) { + return FALSE; + } + int32_t nLen = wsText.GetLength(); + CFX_WideString l = wsText.Mid(0, caretPos); + CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos); + CFX_WideString wsNew = l + cNum + r; + if (wsNew.GetInteger() <= m_iMax) { + return TRUE; + } + } else { + if (wsText.GetInteger() <= m_iMax) { + return TRUE; + } + } + return FALSE; +} +void CFWL_EditImp::InitCaret() { + if (!m_pCaret) { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) { + CFWL_WidgetImpProperties prop; + m_pCaret.reset(IFWL_Caret::Create(prop, m_pInterface)); + m_pCaret->Initialize(); + m_pCaret->SetParent(m_pInterface); + m_pCaret->SetStates(m_pProperties->m_dwStates); + } + } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) == + 0) { + m_pCaret.reset(); + } +} +void CFWL_EditImp::ClearRecord() { + m_iCurRecord = -1; + m_RecordArr.RemoveAll(); +} +void CFWL_EditImp::ProcessInsertError(int32_t iError) { + switch (iError) { + case -2: { + CFWL_EvtEdtTextFull textFullEvent; + textFullEvent.m_pSrcTarget = m_pInterface; + DispatchEvent(&textFullEvent); + break; + } + default: {} + } +} +CFWL_EditImpDelegate::CFWL_EditImpDelegate(CFWL_EditImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_EditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + int32_t iRet = 1; + switch (dwMsgCode) { + case FWL_MSGHASH_Activate: { + DoActivate(static_cast<CFWL_MsgActivate*>(pMessage)); + break; + } + case FWL_MSGHASH_Deactivate: { + DoDeactivate(static_cast<CFWL_MsgDeactivate*>(pMessage)); + break; + } + 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_LButtonDblClk: { + OnButtonDblClk(pMsg); + break; + } + case FWL_MSGMOUSECMD_MouseMove: { + OnMouseMove(pMsg); + break; + } + case FWL_MSGMOUSECMD_RButtonDown: { + DoButtonDown(pMsg); + break; + } + default: {} + } + break; + } + case FWL_MSGHASH_Key: { + CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); + FX_DWORD dwCmd = pKey->m_dwCmd; + if (dwCmd == FWL_MSGKEYCMD_KeyDown) { + OnKeyDown(pKey); + } else if (dwCmd == FWL_MSGKEYCMD_Char) { + OnChar(pKey); + } + break; + } + default: { iRet = 0; } + } + CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); + return iRet; +} +FWL_ERR CFWL_EditImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + if (!pEvent) + return FWL_ERR_Indefinite; + FX_DWORD dwHashCode = pEvent->GetClassID(); + if (dwHashCode != FWL_EVTHASH_Scroll) { + return FWL_ERR_Succeeded; + } + IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget; + if ((pSrcTarget == m_pOwner->m_pVertScrollBar.get() && + m_pOwner->m_pVertScrollBar) || + (pSrcTarget == m_pOwner->m_pHorzScrollBar.get() && + m_pOwner->m_pHorzScrollBar)) { + CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); + OnScroll(static_cast<IFWL_ScrollBar*>(pSrcTarget), + pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_EditImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_EditImpDelegate::DoActivate(CFWL_MsgActivate* pMsg) { + m_pOwner->m_pProperties->m_dwStates |= ~FWL_WGTSTATE_Deactivated; + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_EditImpDelegate::DoDeactivate(CFWL_MsgDeactivate* pMsg) { + m_pOwner->m_pProperties->m_dwStates &= FWL_WGTSTATE_Deactivated; + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_EditImpDelegate::DoButtonDown(CFWL_MsgMouse* pMsg) { + if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + m_pOwner->SetFocus(TRUE); + } + if (!m_pOwner->m_pEdtEngine) { + m_pOwner->UpdateEditEngine(); + } + IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0); + if (!pPage) + return; + CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); + m_pOwner->DeviceToEngine(pt); + FX_BOOL bBefore = TRUE; + int32_t nIndex = pPage->GetCharIndex(pt, bBefore); + if (nIndex < 0) { + nIndex = 0; + } + m_pOwner->m_pEdtEngine->SetCaretPos(nIndex, bBefore); +} +void CFWL_EditImpDelegate::OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet) { + FX_DWORD dwStyleEx = m_pOwner->GetStylesEx(); + FX_BOOL bRepaint = dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret; + if (bSet) { + m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; + if (!m_pOwner->m_pEdtEngine) { + m_pOwner->UpdateEditEngine(); + } + m_pOwner->UpdateVAlignment(); + m_pOwner->UpdateOffset(); + m_pOwner->UpdateCaret(); + } else if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; + m_pOwner->ShowCaret(FALSE); + if (m_pOwner->m_pEdtEngine && + (dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) { + int32_t nSel = m_pOwner->CountSelRanges(); + if (nSel > 0) { + m_pOwner->ClearSelections(); + bRepaint = TRUE; + } + m_pOwner->SetCaretPos(0); + m_pOwner->UpdateOffset(); + } + m_pOwner->ClearRecord(); + } + m_pOwner->LayoutScrollBar(); + if (bRepaint) { + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width, + m_pOwner->m_pProperties->m_rtWidget.height); + m_pOwner->Repaint(&rtInvalidate); + } +} +void CFWL_EditImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + DoCursor(pMsg); + if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + return; + } + m_pOwner->m_bLButtonDown = TRUE; + m_pOwner->SetGrab(TRUE); + DoButtonDown(pMsg); + int32_t nIndex = m_pOwner->m_pEdtEngine->GetCaretPos(); + FX_BOOL bRepaint = FALSE; + int32_t iCount = m_pOwner->m_pEdtEngine->CountSelRanges(); + if (iCount > 0) { + m_pOwner->m_pEdtEngine->ClearSelection(); + bRepaint = TRUE; + } + FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift; + if (bShift && m_pOwner->m_nSelStart != nIndex) { + int32_t iStart = std::min(m_pOwner->m_nSelStart, nIndex); + int32_t iEnd = std::max(m_pOwner->m_nSelStart, nIndex); + m_pOwner->m_pEdtEngine->AddSelRange(iStart, iEnd - iStart); + bRepaint = TRUE; + } else { + m_pOwner->m_nSelStart = nIndex; + } + if (bRepaint) { + m_pOwner->Repaint(&m_pOwner->m_rtEngine); + } +} +void CFWL_EditImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + DoCursor(pMsg); + m_pOwner->m_bLButtonDown = FALSE; + m_pOwner->SetGrab(FALSE); +} +void CFWL_EditImpDelegate::OnButtonDblClk(CFWL_MsgMouse* pMsg) { + if (!m_pOwner->m_pEdtEngine) + return; + DoCursor(pMsg); + IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0); + if (!pPage) + return; + CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); + m_pOwner->DeviceToEngine(pt); + int32_t nCount = 0; + int32_t nIndex = pPage->SelectWord(pt, nCount); + if (nIndex < 0) { + return; + } + m_pOwner->m_pEdtEngine->AddSelRange(nIndex, nCount); + m_pOwner->m_pEdtEngine->SetCaretPos(nIndex + nCount - 1, FALSE); + m_pOwner->Repaint(&m_pOwner->m_rtEngine); +} +void CFWL_EditImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + if (!m_pOwner->m_pEdtEngine) + return; + DoCursor(pMsg); + if (m_pOwner->m_nSelStart == -1 || !m_pOwner->m_bLButtonDown) { + return; + } + IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0); + if (!pPage) + return; + CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); + m_pOwner->DeviceToEngine(pt); + FX_BOOL bBefore = TRUE; + int32_t nIndex = pPage->GetCharIndex(pt, bBefore); + m_pOwner->m_pEdtEngine->SetCaretPos(nIndex, bBefore); + nIndex = m_pOwner->m_pEdtEngine->GetCaretPos(); + m_pOwner->m_pEdtEngine->ClearSelection(); + if (nIndex != m_pOwner->m_nSelStart) { + int32_t nLen = m_pOwner->m_pEdtEngine->GetTextLength(); + if (m_pOwner->m_nSelStart >= nLen) { + m_pOwner->m_nSelStart = nLen; + } + m_pOwner->m_pEdtEngine->AddSelRange( + std::min(m_pOwner->m_nSelStart, nIndex), + FXSYS_abs(nIndex - m_pOwner->m_nSelStart)); + } +} +void CFWL_EditImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) { + if (!m_pOwner->m_pEdtEngine) + return; + FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone; + FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift; + FX_BOOL bCtrl = pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl; + FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; + switch (dwKeyCode) { + case FWL_VKEY_Left: { + MoveCaret = MC_Left; + break; + } + case FWL_VKEY_Right: { + MoveCaret = MC_Right; + break; + } + case FWL_VKEY_Up: { + MoveCaret = MC_Up; + break; + } + case FWL_VKEY_Down: { + MoveCaret = MC_Down; + break; + } + case FWL_VKEY_Home: { + if (bCtrl) { + MoveCaret = MC_Home; + } else { + MoveCaret = MC_LineStart; + } + break; + } + case FWL_VKEY_End: { + if (bCtrl) { + MoveCaret = MC_End; + } else { + MoveCaret = MC_LineEnd; + } + break; + } + case FWL_VKEY_Insert: { + break; + } + case FWL_VKEY_Delete: { + if ((m_pOwner->m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_EDT_ReadOnly) || + (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { + break; + } + int32_t nCaret = m_pOwner->m_pEdtEngine->GetCaretPos(); +#if (_FX_OS_ == _FX_MACOSX_) + m_pOwner->m_pEdtEngine->Delete(nCaret, TRUE); +#else + m_pOwner->m_pEdtEngine->Delete(nCaret); +#endif + break; + } + case FWL_VKEY_F2: { + break; + } + case FWL_VKEY_Tab: { + m_pOwner->DispatchKeyEvent(pMsg); + break; + } + default: { +#if (_FX_OS_ == _FX_MACOSX_) + if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) { +#else + if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) { +#endif + if (dwKeyCode == 0x43 || dwKeyCode == 0x63) { + m_pOwner->DoClipboard(1); + return; + } + if (dwKeyCode == 0x58 || dwKeyCode == 0x78) { + m_pOwner->DoClipboard(2); + return; + } + if (dwKeyCode == 0x56 || dwKeyCode == 0x76) { + m_pOwner->DoClipboard(3); + return; + } + } + } + } + if (MoveCaret != MC_MoveNone) { + m_pOwner->m_pEdtEngine->MoveCaretPos(MoveCaret, bShift, bCtrl); + } +} +void CFWL_EditImpDelegate::OnChar(CFWL_MsgKey* pMsg) { + if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || + (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { + return; + } + if (!m_pOwner->m_pEdtEngine) + return; + int32_t iError = 0; + FX_WCHAR c = (FX_WCHAR)pMsg->m_dwKeyCode; + int32_t nCaret = m_pOwner->m_pEdtEngine->GetCaretPos(); + switch (c) { + case FWL_VKEY_Back: { + m_pOwner->m_pEdtEngine->Delete(nCaret, TRUE); + break; + } + case 0x0A: { + break; + } + case FWL_VKEY_Escape: { + break; + } + case FWL_VKEY_Tab: { + iError = m_pOwner->m_pEdtEngine->Insert(nCaret, L"\t", 1); + break; + } + case FWL_VKEY_Return: { + if (m_pOwner->m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_EDT_WantReturn) { + iError = m_pOwner->m_pEdtEngine->Insert(nCaret, L"\n", 1); + } + break; + } + default: { + if (!m_pOwner->m_pWidgetMgr->IsFormDisabled()) { + if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) { + if (((pMsg->m_dwKeyCode < FWL_VKEY_0) && + (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) || + pMsg->m_dwKeyCode > FWL_VKEY_9) { + break; + } + if (!m_pOwner->ValidateNumberChar(c)) { + break; + } + } + } +#if (_FX_OS_ == _FX_MACOSX_) + if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) +#else + if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) +#endif + { + break; + } + iError = m_pOwner->m_pEdtEngine->Insert(nCaret, &c, 1); + break; + } + } + if (iError < 0) { + m_pOwner->ProcessInsertError(iError); + } +} +FX_BOOL CFWL_EditImpDelegate::OnScroll(IFWL_ScrollBar* pScrollBar, + FX_DWORD dwCode, + FX_FLOAT fPos) { + CFX_SizeF fs; + pScrollBar->GetRange(fs.x, fs.y); + FX_FLOAT iCurPos = pScrollBar->GetPos(); + FX_FLOAT fStep = pScrollBar->GetStepSize(); + switch (dwCode) { + case FWL_SCBCODE_Min: { + fPos = fs.x; + break; + } + case FWL_SCBCODE_Max: { + fPos = fs.y; + break; + } + case FWL_SCBCODE_StepBackward: { + fPos -= fStep; + if (fPos < fs.x + fStep / 2) { + fPos = fs.x; + } + break; + } + case FWL_SCBCODE_StepForward: { + fPos += fStep; + if (fPos > fs.y - fStep / 2) { + fPos = fs.y; + } + break; + } + case FWL_SCBCODE_PageBackward: { + fPos -= pScrollBar->GetPageSize(); + if (fPos < fs.x) { + fPos = fs.x; + } + break; + } + case FWL_SCBCODE_PageForward: { + fPos += pScrollBar->GetPageSize(); + if (fPos > fs.y) { + fPos = fs.y; + } + break; + } + case FWL_SCBCODE_Pos: + case FWL_SCBCODE_TrackPos: { + break; + } + case FWL_SCBCODE_EndScroll: { + return FALSE; + } + default: {} + } + if (iCurPos != fPos) { + pScrollBar->SetPos(fPos); + pScrollBar->SetTrackPos(fPos); + m_pOwner->UpdateOffset(pScrollBar, fPos - iCurPos); + if (m_pOwner->m_pEdtEngine) { + m_pOwner->UpdateCaret(); + } + CFX_RectF rect; + m_pOwner->GetWidgetRect(rect); + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2); + m_pOwner->Repaint(&rtInvalidate); + } + return TRUE; +} +void CFWL_EditImpDelegate::DoCursor(CFWL_MsgMouse* pMsg) {} diff --git a/xfa/src/fwl/basewidget/fwl_editimp.h b/xfa/src/fwl/basewidget/fwl_editimp.h new file mode 100644 index 0000000000..0dbdca27a0 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_editimp.h @@ -0,0 +1,208 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_EDITIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_EDITIMP_H_ + +#include <memory> +#include <vector> + +#include "xfa/include/fwl/basewidget/fwl_scrollbar.h" +#include "xfa/src/fee/include/ifde_txtedtengine.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class CFWL_WidgetImpDelegate; +class IFWL_Caret; +class CFWL_EditImp; +class CFWL_EditImpDelegate; + +class CFWL_EditImp : public CFWL_WidgetImp, public IFDE_TxtEdtEventSink { + public: + CFWL_EditImp(const CFWL_WidgetImpProperties& properties, IFWL_Widget* pOuter); + ~CFWL_EditImp() override; + + // CFWL_WidgetImp: + FWL_ERR GetClassName(CFX_WideString& wsClass) const override; + FX_DWORD GetClassID() const override; + FWL_ERR Initialize() override; + FWL_ERR Finalize() override; + FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE) override; + FWL_ERR SetWidgetRect(const CFX_RectF& rect) override; + FWL_ERR Update() override; + FX_DWORD HitTest(FX_FLOAT fx, FX_FLOAT fy) override; + FWL_ERR SetStates(FX_DWORD dwStates, FX_BOOL bSet = TRUE) override; + FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + FWL_ERR SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override; + + virtual FWL_ERR SetText(const CFX_WideString& wsText); + virtual int32_t GetTextLength() const; + virtual FWL_ERR GetText(CFX_WideString& wsText, + int32_t nStart = 0, + int32_t nCount = -1) const; + virtual FWL_ERR ClearText(); + virtual int32_t GetCaretPos() const; + virtual int32_t SetCaretPos(int32_t nIndex, FX_BOOL bBefore = TRUE); + virtual FWL_ERR AddSelRange(int32_t nStart, int32_t nCount = -1); + virtual int32_t CountSelRanges(); + virtual int32_t GetSelRange(int32_t nIndex, int32_t& nStart); + virtual FWL_ERR ClearSelections(); + virtual int32_t GetLimit(); + virtual FWL_ERR SetLimit(int32_t nLimit); + virtual FWL_ERR SetAliasChar(FX_WCHAR wAlias); + virtual FWL_ERR Insert(int32_t nStart, const FX_WCHAR* lpText, int32_t nLen); + virtual FWL_ERR DeleteSelections(); + virtual FWL_ERR DeleteRange(int32_t nStart, int32_t nCount = -1); + virtual FWL_ERR ReplaceSelections(const CFX_WideStringC& wsReplace); + virtual FWL_ERR Replace(int32_t nStart, + int32_t nLen, + const CFX_WideStringC& wsReplace); + virtual FWL_ERR DoClipboard(int32_t iCmd); + virtual FX_BOOL Copy(CFX_WideString& wsCopy); + virtual FX_BOOL Cut(CFX_WideString& wsCut); + virtual FX_BOOL Paste(const CFX_WideString& wsPaste); + virtual FX_BOOL Delete(); + virtual FX_BOOL Redo(const CFX_ByteStringC& bsRecord); + virtual FX_BOOL Undo(const CFX_ByteStringC& bsRecord); + virtual FX_BOOL Undo(); + virtual FX_BOOL Redo(); + virtual FX_BOOL CanUndo(); + virtual FX_BOOL CanRedo(); + virtual FWL_ERR SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant); + virtual FWL_ERR SetOuter(IFWL_Widget* pOuter); + virtual FWL_ERR SetNumberRange(int32_t iMin, int32_t iMax); + void On_CaretChanged(IFDE_TxtEdtEngine* pEdit, + int32_t nPage, + FX_BOOL bVisible = true) override; + void On_TextChanged(IFDE_TxtEdtEngine* pEdit, + FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) override; + void On_PageCountChanged(IFDE_TxtEdtEngine* pEdit) override {} + void On_SelChanged(IFDE_TxtEdtEngine* pEdit) override; + FX_BOOL On_PageLoad(IFDE_TxtEdtEngine* pEdit, + int32_t nPageIndex, + int32_t nPurpose) override; + FX_BOOL On_PageUnload(IFDE_TxtEdtEngine* pEdit, + int32_t nPageIndex, + int32_t nPurpose) override; + FX_BOOL On_PageChange(IFDE_TxtEdtEngine* pEdit, int32_t nPageIndex) override { + return TRUE; + } + void On_AddDoRecord(IFDE_TxtEdtEngine* pEdit, + const CFX_ByteStringC& bsDoRecord) override; + FX_BOOL On_ValidateField(IFDE_TxtEdtEngine* pEdit, + int32_t nBlockIndex, + int32_t nFieldIndex, + const CFX_WideString& wsFieldText, + int32_t nCharIndex) override; + FX_BOOL On_ValidateBlock(IFDE_TxtEdtEngine* pEdit, + int32_t nBlockIndex) override; + FX_BOOL On_GetBlockFormatText(IFDE_TxtEdtEngine* pEdit, + int32_t nBlockIndex, + CFX_WideString& wsBlockText) override; + FX_BOOL On_Validate(IFDE_TxtEdtEngine* pEdit, + CFX_WideString& wsText) override; + virtual FWL_ERR SetBackgroundColor(FX_DWORD color); + virtual FWL_ERR SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize); + void SetScrollOffset(FX_FLOAT fScrollOffset); + FX_BOOL GetSuggestWords(CFX_PointF pointf, + std::vector<CFX_ByteString>& sSuggest); + FX_BOOL ReplaceSpellCheckWord(CFX_PointF pointf, + const CFX_ByteStringC& bsReplace); + + protected: + void DrawTextBk(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix = NULL); + void DrawContent(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix = NULL); + void UpdateEditEngine(); + void UpdateEditParams(); + void UpdateEditLayout(); + FX_BOOL UpdateOffset(); + FX_BOOL UpdateOffset(IFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged); + void UpdateVAlignment(); + void UpdateCaret(); + IFWL_ScrollBar* UpdateScroll(); + void Layout(); + void LayoutScrollBar(); + void DeviceToEngine(CFX_PointF& pt); + void InitScrollBar(FX_BOOL bVert = TRUE); + void InitEngine(); + virtual void ShowCaret(FX_BOOL bVisible, CFX_RectF* pRect = NULL); + FX_BOOL ValidateNumberChar(FX_WCHAR cNum); + void InitCaret(); + void ClearRecord(); + FX_BOOL IsShowScrollBar(FX_BOOL bVert); + FX_BOOL IsContentHeightOverflow(); + int32_t AddDoRecord(const CFX_ByteStringC& bsDoRecord); + void ProcessInsertError(int32_t iError); + + void DrawSpellCheck(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + void AddSpellCheckObj(CFX_Path& PathData, + int32_t nStart, + int32_t nCount, + FX_FLOAT fOffSetX, + FX_FLOAT fOffSetY); + int32_t GetWordAtPoint(CFX_PointF pointf, int32_t& nCount); + CFX_RectF m_rtClient; + CFX_RectF m_rtEngine; + CFX_RectF m_rtStatic; + FX_FLOAT m_fVAlignOffset; + FX_FLOAT m_fScrollOffsetX; + FX_FLOAT m_fScrollOffsetY; + IFDE_TxtEdtEngine* m_pEdtEngine; + FX_BOOL m_bLButtonDown; + int32_t m_nSelStart; + int32_t m_nLimit; + FX_FLOAT m_fSpaceAbove; + FX_FLOAT m_fSpaceBelow; + FX_FLOAT m_fFontSize; + FX_ARGB m_argbSel; + FX_BOOL m_bSetRange; + int32_t m_iMin; + int32_t m_iMax; + std::unique_ptr<IFWL_ScrollBar> m_pVertScrollBar; + std::unique_ptr<IFWL_ScrollBar> m_pHorzScrollBar; + std::unique_ptr<IFWL_Caret> m_pCaret; + CFX_WideString m_wsCache; + friend class CFWL_TxtEdtEventSink; + friend class CFWL_EditImpDelegate; + FX_DWORD m_backColor; + FX_BOOL m_updateBackColor; + CFX_WideString m_wsFont; + CFX_ByteStringArray m_RecordArr; + int32_t m_iCurRecord; + int32_t m_iMaxRecord; +}; + +class CFWL_EditImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_EditImpDelegate(CFWL_EditImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void DoActivate(CFWL_MsgActivate* pMsg); + void DoDeactivate(CFWL_MsgDeactivate* pMsg); + void DoButtonDown(CFWL_MsgMouse* pMsg); + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnButtonDblClk(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnKeyDown(CFWL_MsgKey* pMsg); + void OnChar(CFWL_MsgKey* pMsg); + FX_BOOL OnScroll(IFWL_ScrollBar* pScrollBar, FX_DWORD dwCode, FX_FLOAT fPos); + void DoCursor(CFWL_MsgMouse* pMsg); + CFWL_EditImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_EDITIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_formproxyimp.cpp b/xfa/src/fwl/basewidget/fwl_formproxyimp.cpp new file mode 100644 index 0000000000..3985f00b77 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_formproxyimp.cpp @@ -0,0 +1,55 @@ +// 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/src/fwl/basewidget/fwl_formproxyimp.h" + +#include "xfa/src/fwl/core/fwl_formimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_panelimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +CFWL_FormProxyImp::CFWL_FormProxyImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_FormImp(properties, pOuter) {} +CFWL_FormProxyImp::~CFWL_FormProxyImp() {} +FWL_ERR CFWL_FormProxyImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_FormProxy; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_FormProxyImp::GetClassID() const { + return FWL_CLASSHASH_FormProxy; +} +FX_BOOL CFWL_FormProxyImp::IsInstance(const CFX_WideStringC& wsClass) const { + if (wsClass == CFX_WideStringC(FWL_CLASS_FormProxy)) { + return TRUE; + } + return CFWL_FormImp::IsInstance(wsClass); +} +FWL_ERR CFWL_FormProxyImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_FormProxyImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_FormProxyImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_FormProxyImp::Update() { + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_FormProxyImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return FWL_ERR_Succeeded; +} +CFWL_FormProxyImpDelegate::CFWL_FormProxyImpDelegate(CFWL_FormProxyImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_FormProxyImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pOuter->SetDelegate(NULL); + return pDelegate->OnProcessMessage(pMessage); +} diff --git a/xfa/src/fwl/basewidget/fwl_formproxyimp.h b/xfa/src/fwl/basewidget/fwl_formproxyimp.h new file mode 100644 index 0000000000..56ef05360c --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_formproxyimp.h @@ -0,0 +1,42 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_FORMPROXYIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_FORMPROXYIMP_H_ + +#include "xfa/src/fwl/core/fwl_formimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class CFWL_FormProxyImpDelegate; + +class CFWL_FormProxyImp : public CFWL_FormImp { + public: + CFWL_FormProxyImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_FormProxyImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FX_BOOL IsInstance(const CFX_WideStringC& wsClass) const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + + protected: + friend class CFWL_FormProxyImpDelegate; +}; +class CFWL_FormProxyImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_FormProxyImpDelegate(CFWL_FormProxyImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + + protected: + CFWL_FormProxyImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_FORMPROXYIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_listboximp.cpp b/xfa/src/fwl/basewidget/fwl_listboximp.cpp new file mode 100644 index 0000000000..26b27e8637 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_listboximp.cpp @@ -0,0 +1,1241 @@ +// 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/src/fwl/basewidget/fwl_listboximp.h" + +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fdp/include/fde_tto.h" +#include "xfa/src/fwl/basewidget/fwl_comboboximp.h" +#include "xfa/src/fwl/basewidget/fwl_scrollbarimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +#define FWL_LISTBOX_ItemTextMargin 2 + +// static +IFWL_ListBox* IFWL_ListBox::Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_ListBox* pListBox = new IFWL_ListBox; + CFWL_ListBoxImp* pListBoxImpl = new CFWL_ListBoxImp(properties, pOuter); + pListBox->SetImpl(pListBoxImpl); + pListBoxImpl->SetInterface(pListBox); + return pListBox; +} +// static +IFWL_ListBox* IFWL_ListBox::CreateComboList( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_ListBox* pListBox = new IFWL_ListBox; + CFWL_ListBoxImp* pComboListImpl = new CFWL_ComboListImp(properties, pOuter); + pListBox->SetImpl(pComboListImpl); + pComboListImpl->SetInterface(pListBox); + return pListBox; +} +IFWL_ListBox::IFWL_ListBox() {} +int32_t IFWL_ListBox::CountSelItems() { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->CountSelItems(); +} +FWL_HLISTITEM IFWL_ListBox::GetSelItem(int32_t nIndexSel) { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetSelItem(nIndexSel); +} +int32_t IFWL_ListBox::GetSelIndex(int32_t nIndex) { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetSelIndex(nIndex); +} +FWL_ERR IFWL_ListBox::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->SetSelItem(hItem, bSelect); +} +FWL_ERR IFWL_ListBox::GetItemText(FWL_HLISTITEM hItem, CFX_WideString& wsText) { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetItemText(hItem, wsText); +} +FWL_ERR IFWL_ListBox::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetScrollPos(fPos, bVert); +} +FWL_ERR* IFWL_ListBox::Sort(IFWL_ListBoxCompare* pCom) { + return static_cast<CFWL_ListBoxImp*>(GetImpl())->Sort(pCom); +} + +CFWL_ListBoxImp::CFWL_ListBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_dwTTOStyles(0), + m_iTTOAligns(0), + m_hAnchor(NULL), + m_fScorllBarWidth(0), + m_bLButtonDown(FALSE), + m_pScrollBarTP(NULL) { + m_rtClient.Reset(); + m_rtConent.Reset(); + m_rtStatic.Reset(); +} +CFWL_ListBoxImp::~CFWL_ListBoxImp() {} +FWL_ERR CFWL_ListBoxImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_ListBox; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ListBoxImp::GetClassID() const { + return FWL_CLASSHASH_ListBox; +} +FWL_ERR CFWL_ListBoxImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_ListBoxImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ListBoxImp::Finalize() { + if (m_pVertScrollBar) { + m_pVertScrollBar->Finalize(); + } + if (m_pHorzScrollBar) { + m_pHorzScrollBar->Finalize(); + } + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_ListBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + CFX_SizeF fs = CalcSize(TRUE); + rect.Set(0, 0, fs.x, fs.y); + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ListBoxImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + m_iTTOAligns = FDE_TTOALIGNMENT_Center; + switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_AlignMask) { + case FWL_STYLEEXT_LTB_LeftAlign: { + m_iTTOAligns = FDE_TTOALIGNMENT_CenterLeft; + break; + } + case FWL_STYLEEXT_LTB_RightAlign: { + m_iTTOAligns = FDE_TTOALIGNMENT_CenterRight; + break; + } + case FWL_STYLEEXT_LTB_CenterAlign: + default: { m_iTTOAligns = FDE_TTOALIGNMENT_Center; } + } + if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) { + m_dwTTOStyles |= FDE_TTOSTYLE_RTL; + } + m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine; + m_fScorllBarWidth = GetScrollWidth(); + SortItem(); + CalcSize(); + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ListBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { + if (IsShowScrollBar(FALSE)) { + CFX_RectF rect; + m_pHorzScrollBar->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_HScrollBar; + } + } + if (IsShowScrollBar(TRUE)) { + CFX_RectF rect; + m_pVertScrollBar->GetWidgetRect(rect); + if (rect.Contains(fx, fy)) { + return FWL_WGTHITTEST_VScrollBar; + } + } + if (m_rtClient.Contains(fx, fy)) { + return FWL_WGTHITTEST_Client; + } + return FWL_WGTHITTEST_Unknown; +} +FWL_ERR CFWL_ListBoxImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + pGraphics->SaveGraphState(); + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_LTB_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_LTB_Edge, pTheme, pMatrix); + } + CFX_RectF rtClip(m_rtConent); + if (IsShowScrollBar(FALSE)) { + rtClip.height -= m_fScorllBarWidth; + } + if (IsShowScrollBar(TRUE)) { + rtClip.width -= m_fScorllBarWidth; + } + if (pMatrix) { + pMatrix->TransformRect(rtClip); + } + pGraphics->SetClipRect(rtClip); + if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_NoBackground) == 0) { + DrawBkground(pGraphics, pTheme, pMatrix); + } + DrawItems(pGraphics, pTheme, pMatrix); + pGraphics->RestoreGraphState(); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ListBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { + if (!pThemeProvider) + return FWL_ERR_Indefinite; + if (!pThemeProvider->IsValidWidget(m_pInterface)) { + m_pScrollBarTP = pThemeProvider; + return FWL_ERR_Succeeded; + } + m_pProperties->m_pThemeProvider = pThemeProvider; + return FWL_ERR_Succeeded; +} +int32_t CFWL_ListBoxImp::CountSelItems() { + if (!m_pProperties->m_pDataProvider) + return 0; + int32_t iRet = 0; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) { + continue; + } + FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); + if (dwStyle & FWL_ITEMSTATE_LTB_Selected) { + iRet++; + } + } + return iRet; +} +FWL_HLISTITEM CFWL_ListBoxImp::GetSelItem(int32_t nIndexSel) { + if (!m_pProperties->m_pDataProvider) + return NULL; + int32_t index = 0; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) { + return NULL; + } + FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); + if (dwStyle & FWL_ITEMSTATE_LTB_Selected) { + if (index == nIndexSel) { + return hItem; + } else { + index++; + } + } + } + return NULL; +} +int32_t CFWL_ListBoxImp::GetSelIndex(int32_t nIndex) { + if (!m_pProperties->m_pDataProvider) + return -1; + int32_t index = 0; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) { + return -1; + } + FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); + if (dwStyle & FWL_ITEMSTATE_LTB_Selected) { + if (index == nIndex) { + return i; + } else { + index++; + } + } + } + return -1; +} +FWL_ERR CFWL_ListBoxImp::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) { + if (!m_pProperties->m_pDataProvider) + return FWL_ERR_Indefinite; + if (!hItem) { + if (bSelect) { + SelectAll(); + } else { + ClearSelection(); + SetFocusItem(NULL); + } + return FWL_ERR_Indefinite; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) { + SetSelectionDirect(hItem, bSelect); + } else { + SetSelection(hItem, hItem, bSelect); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ListBoxImp::GetItemText(FWL_HLISTITEM hItem, + CFX_WideString& wsText) { + if (!m_pProperties->m_pDataProvider) + return FWL_ERR_Indefinite; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + if (!hItem) + return FWL_ERR_Indefinite; + pData->GetItemText(m_pInterface, hItem, wsText); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ListBoxImp::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) { + if ((bVert && IsShowScrollBar(TRUE)) || (!bVert && IsShowScrollBar(FALSE))) { + IFWL_ScrollBar* pScrollBar = + bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get(); + fPos = pScrollBar->GetPos(); + return FWL_ERR_Succeeded; + } + return FWL_ERR_Indefinite; +} +FWL_ERR* CFWL_ListBoxImp::Sort(IFWL_ListBoxCompare* pCom) { + FWL_HLISTITEM hTemp; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t sz = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < sz - 1; i++) { + for (int32_t j = i + 1; j < sz; j++) { + if (pCom->Compare(pData->GetItem(m_pInterface, i), + pData->GetItem(m_pInterface, j)) > 0) { + hTemp = pData->GetItem(m_pInterface, i); + pData->SetItemIndex(m_pInterface, pData->GetItem(m_pInterface, j), i); + pData->SetItemIndex(m_pInterface, hTemp, j); + } + } + } + return FWL_ERR_Succeeded; +} +FWL_HLISTITEM CFWL_ListBoxImp::GetItem(FWL_HLISTITEM hItem, + FX_DWORD dwKeyCode) { + FWL_HLISTITEM hRet = NULL; + switch (dwKeyCode) { + case FWL_VKEY_Up: + case FWL_VKEY_Down: + case FWL_VKEY_Home: + case FWL_VKEY_End: { + const bool bUp = dwKeyCode == FWL_VKEY_Up; + const bool bDown = dwKeyCode == FWL_VKEY_Down; + const bool bHome = dwKeyCode == FWL_VKEY_Home; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iDstItem = -1; + if (bUp || bDown) { + int32_t index = pData->GetItemIndex(m_pInterface, hItem); + iDstItem = dwKeyCode == FWL_VKEY_Up ? index - 1 : index + 1; + } else if (bHome) { + iDstItem = 0; + } else { + int32_t iCount = pData->CountItems(m_pInterface); + iDstItem = iCount - 1; + } + hRet = pData->GetItem(m_pInterface, iDstItem); + break; + } + default: {} + } + return hRet; +} +void CFWL_ListBoxImp::SetSelection(FWL_HLISTITEM hStart, + FWL_HLISTITEM hEnd, + FX_BOOL bSelected) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iStart = pData->GetItemIndex(m_pInterface, hStart); + int32_t iEnd = pData->GetItemIndex(m_pInterface, hEnd); + if (iStart > iEnd) { + int32_t iTemp = iStart; + iStart = iEnd; + iEnd = iTemp; + } + if (bSelected) { + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + SetSelectionDirect(hItem, FALSE); + } + } + for (; iStart <= iEnd; iStart++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iStart); + SetSelectionDirect(hItem, bSelected); + } +} +void CFWL_ListBoxImp::SetSelectionDirect(FWL_HLISTITEM hItem, FX_BOOL bSelect) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + FX_DWORD dwOldStyle = pData->GetItemStyles(m_pInterface, hItem); + bSelect ? dwOldStyle |= FWL_ITEMSTATE_LTB_Selected + : dwOldStyle &= ~FWL_ITEMSTATE_LTB_Selected; + pData->SetItemStyles(m_pInterface, hItem, dwOldStyle); +} +FX_BOOL CFWL_ListBoxImp::IsItemSelected(FWL_HLISTITEM hItem) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + FX_DWORD dwState = pData->GetItemStyles(m_pInterface, hItem); + return (dwState & FWL_ITEMSTATE_LTB_Selected) != 0; +} +void CFWL_ListBoxImp::ClearSelection() { + FX_BOOL bMulti = + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + FX_DWORD dwState = pData->GetItemStyles(m_pInterface, hItem); + FX_BOOL bFindSel = dwState & FWL_ITEMSTATE_LTB_Selected; + if (!bFindSel) { + continue; + } + SetSelectionDirect(hItem, FALSE); + if (!bMulti) { + return; + } + } +} +void CFWL_ListBoxImp::SelectAll() { + FX_BOOL bMulti = + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection; + if (!bMulti) { + return; + } + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + if (iCount > 0) { + FWL_HLISTITEM hItemStart = pData->GetItem(m_pInterface, 0); + FWL_HLISTITEM hItemEnd = pData->GetItem(m_pInterface, iCount - 1); + SetSelection(hItemStart, hItemEnd, FALSE); + } +} +FWL_HLISTITEM CFWL_ListBoxImp::GetFocusedItem() { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) + return NULL; + if (pData->GetItemStyles(m_pInterface, hItem) & FWL_ITEMSTATE_LTB_Focused) { + return hItem; + } + } + return NULL; +} +void CFWL_ListBoxImp::SetFocusItem(FWL_HLISTITEM hItem) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + FWL_HLISTITEM hFocus = GetFocusedItem(); + if (hItem != hFocus) { + if (hFocus) { + FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hFocus); + dwStyle &= ~FWL_ITEMSTATE_LTB_Focused; + pData->SetItemStyles(m_pInterface, hFocus, dwStyle); + } + if (hItem) { + FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); + dwStyle |= FWL_ITEMSTATE_LTB_Focused; + pData->SetItemStyles(m_pInterface, hItem, dwStyle); + } + } +} +FWL_HLISTITEM CFWL_ListBoxImp::GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy) { + fx -= m_rtConent.left, fy -= m_rtConent.top; + FX_FLOAT fPosX = 0.0f; + if (m_pHorzScrollBar) { + fPosX = m_pHorzScrollBar->GetPos(); + } + FX_FLOAT fPosY = 0.0; + if (m_pVertScrollBar) { + fPosY = m_pVertScrollBar->GetPos(); + } + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t nCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < nCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) { + continue; + } + CFX_RectF rtItem; + pData->GetItemRect(m_pInterface, hItem, rtItem); + rtItem.Offset(-fPosX, -fPosY); + if (rtItem.Contains(fx, fy)) { + return hItem; + } + } + return NULL; +} +FX_BOOL CFWL_ListBoxImp::GetItemCheckRect(FWL_HLISTITEM hItem, + CFX_RectF& rtCheck) { + if (!m_pProperties->m_pDataProvider) + return FALSE; + if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) { + return FALSE; + } + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + pData->GetItemCheckRect(m_pInterface, hItem, rtCheck); + return TRUE; +} +FX_BOOL CFWL_ListBoxImp::GetItemChecked(FWL_HLISTITEM hItem) { + if (!m_pProperties->m_pDataProvider) + return FALSE; + if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) { + return FALSE; + } + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + return (pData->GetItemCheckState(m_pInterface, hItem) & + FWL_ITEMSTATE_LTB_Checked); +} +FX_BOOL CFWL_ListBoxImp::SetItemChecked(FWL_HLISTITEM hItem, FX_BOOL bChecked) { + if (!m_pProperties->m_pDataProvider) + return FALSE; + if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) { + return FALSE; + } + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + pData->SetItemCheckState(m_pInterface, hItem, + bChecked ? FWL_ITEMSTATE_LTB_Checked : 0); + return TRUE; +} +FX_BOOL CFWL_ListBoxImp::ScrollToVisible(FWL_HLISTITEM hItem) { + if (!m_pVertScrollBar) + return FALSE; + CFX_RectF rtItem; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + pData->GetItemRect(m_pInterface, hItem, rtItem); + FX_BOOL bScroll = FALSE; + FX_FLOAT fPosY = m_pVertScrollBar->GetPos(); + rtItem.Offset(0, -fPosY + m_rtConent.top); + if (rtItem.top < m_rtConent.top) { + fPosY += rtItem.top - m_rtConent.top; + bScroll = TRUE; + } else if (rtItem.bottom() > m_rtConent.bottom()) { + fPosY += rtItem.bottom() - m_rtConent.bottom(); + bScroll = TRUE; + } + if (!bScroll) { + return FALSE; + } + m_pVertScrollBar->SetPos(fPosY); + m_pVertScrollBar->SetTrackPos(fPosY); + Repaint(&m_rtClient); + return TRUE; +} +void CFWL_ListBoxImp::DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return; + if (!pTheme) + return; + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_LTB_Background; + param.m_dwStates = 0; + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = m_rtClient; + if (IsShowScrollBar(FALSE) && IsShowScrollBar(TRUE)) { + param.m_pData = &m_rtStatic; + } + if (!IsEnabled()) { + param.m_dwStates = FWL_PARTSTATE_LTB_Disabled; + } + pTheme->DrawBackground(¶m); +} +void CFWL_ListBoxImp::DrawItems(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + FX_FLOAT fPosX = 0.0f; + if (m_pHorzScrollBar) { + fPosX = m_pHorzScrollBar->GetPos(); + } + FX_FLOAT fPosY = 0.0f; + if (m_pVertScrollBar) { + fPosY = m_pVertScrollBar->GetPos(); + } + CFX_RectF rtView(m_rtConent); + if (m_pHorzScrollBar) { + rtView.height -= m_fScorllBarWidth; + } + if (m_pVertScrollBar) { + rtView.width -= m_fScorllBarWidth; + } + FX_BOOL bMultiCol = + m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) { + continue; + } + CFX_RectF rtItem; + pData->GetItemRect(m_pInterface, hItem, rtItem); + rtItem.Offset(m_rtConent.left - fPosX, m_rtConent.top - fPosY); + if (rtItem.bottom() < m_rtConent.top) { + continue; + } + if (rtItem.top >= m_rtConent.bottom()) { + break; + } + if (bMultiCol && rtItem.left > m_rtConent.right()) { + break; + } + if (GetStylesEx() & FWL_STYLEEXT_LTB_OwnerDraw) { + CFWL_EvtLtbDrawItem ev; + ev.m_pSrcTarget = m_pInterface; + ev.m_pGraphics = pGraphics; + ev.m_matrix = *pMatrix; + ev.m_index = i; + ev.m_rect = rtItem; + DispatchEvent(&ev); + } else { + DrawItem(pGraphics, pTheme, hItem, i, rtItem, pMatrix); + } + } +} +void CFWL_ListBoxImp::DrawItem(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + FWL_HLISTITEM hItem, + int32_t Index, + const CFX_RectF& rtItem, + const CFX_Matrix* pMatrix) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + FX_DWORD dwItemStyles = pData->GetItemStyles(m_pInterface, hItem); + FX_DWORD dwPartStates = FWL_PARTSTATE_LTB_Normal; + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + dwPartStates = FWL_PARTSTATE_LTB_Disabled; + } else if (dwItemStyles & FWL_ITEMSTATE_LTB_Selected) { + dwPartStates = FWL_PARTSTATE_LTB_Selected; + } + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && + dwItemStyles & FWL_ITEMSTATE_LTB_Focused) { + dwPartStates |= FWL_PARTSTATE_LTB_Focused; + } + FWL_ListBoxItemData itemData; + itemData.pDataProvider = pData; + itemData.iIndex = Index; + { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_LTB_ListItem; + param.m_dwStates = dwPartStates; + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = rtItem; + param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); + CFX_RectF rtFocus(rtItem); + param.m_pData = &rtFocus; + if (m_pVertScrollBar && !m_pHorzScrollBar && + (dwPartStates & FWL_PARTSTATE_LTB_Focused)) { + param.m_rtPart.left += 1; + param.m_rtPart.width -= (m_fScorllBarWidth + 1); + rtFocus.Deflate(0.5, 0.5, 1 + m_fScorllBarWidth, 1); + } + pTheme->DrawBackground(¶m); + } + { + FX_BOOL bHasIcon = GetStylesEx() & FWL_STYLEEXT_LTB_Icon; + if (bHasIcon) { + CFX_RectF rtDIB; + CFX_DIBitmap* pDib = pData->GetItemIcon(m_pInterface, hItem); + rtDIB.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height); + if (pDib) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_LTB_Icon; + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = rtDIB; + param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); + param.m_pImage = pDib; + pTheme->DrawBackground(¶m); + } + } + FX_BOOL bHasCheck = GetStylesEx() & FWL_STYLEEXT_LTB_Check; + if (bHasCheck) { + CFX_RectF rtCheck; + rtCheck.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height); + rtCheck.Deflate(2, 2, 2, 2); + pData->SetItemCheckRect(m_pInterface, hItem, rtCheck); + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_LTB_Check; + param.m_pGraphics = pGraphics; + if (GetItemChecked(hItem)) { + param.m_dwStates = FWL_PARTSTATE_LTB_Checked; + } else { + param.m_dwStates = FWL_PARTSTATE_LTB_UnChecked; + } + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = rtCheck; + param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); + pTheme->DrawBackground(¶m); + } + CFX_WideString wsText; + pData->GetItemText(m_pInterface, hItem, wsText); + if (wsText.GetLength() <= 0) { + return; + } + CFX_RectF rtText(rtItem); + rtText.Deflate(FWL_LISTBOX_ItemTextMargin, FWL_LISTBOX_ItemTextMargin); + if (bHasIcon || bHasCheck) { + rtText.Deflate(rtItem.height, 0, 0, 0); + } + CFWL_ThemeText textParam; + textParam.m_pWidget = m_pInterface; + textParam.m_iPart = FWL_PART_LTB_ListItem; + textParam.m_dwStates = dwPartStates; + textParam.m_pGraphics = pGraphics; + textParam.m_matrix.Concat(*pMatrix); + textParam.m_rtPart = rtText; + textParam.m_wsText = wsText; + textParam.m_dwTTOStyles = m_dwTTOStyles; + textParam.m_iTTOAlign = m_iTTOAligns; + textParam.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); + pTheme->DrawText(&textParam); + } +} +CFX_SizeF CFWL_ListBoxImp::CalcSize(FX_BOOL bAutoSize) { + CFX_SizeF fs; + if (!m_pProperties->m_pThemeProvider) + return fs; + + GetClientRect(m_rtClient); + m_rtConent = m_rtClient; + CFX_RectF rtUIMargin; + rtUIMargin.Set(0, 0, 0, 0); + if (!m_pOuter) { + CFX_RectF* pUIMargin = + static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin)); + if (pUIMargin) { + m_rtConent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, + pUIMargin->height); + } + } + FX_FLOAT fWidth = 0; + if (m_pProperties->m_pThemeProvider->IsCustomizedLayout(m_pInterface)) { + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + if (!bAutoSize) { + } + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + CFWL_ThemePart itemPart; + itemPart.m_pWidget = m_pInterface; + itemPart.m_iPart = FWL_PART_LTB_ListItem; + itemPart.m_pData = m_pProperties->m_pDataProvider; + itemPart.m_dwData = i; + CFX_RectF r; + m_pProperties->m_pThemeProvider->GetPartRect(&itemPart, r); + if (!bAutoSize) { + CFX_RectF rtItem; + rtItem.Set(m_rtClient.left, m_rtClient.top + fs.y, r.width, r.height); + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + pData->SetItemRect(m_pInterface, hItem, rtItem); + } + fs.y += r.height; + if (fs.x < r.width) { + fs.x = r.width; + fWidth = r.width; + } + } + } else { + fWidth = GetMaxTextWidth(); + fWidth += 2 * FWL_LISTBOX_ItemTextMargin; + if (!bAutoSize) { + FX_FLOAT fActualWidth = + m_rtClient.width - rtUIMargin.left - rtUIMargin.width; + if (fWidth < fActualWidth) { + fWidth = fActualWidth; + } + } + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + m_fItemHeight = GetItemHeigt(); + FX_BOOL bHasIcon; + bHasIcon = GetStylesEx() & FWL_STYLEEXT_LTB_Icon; + if (bHasIcon) { + fWidth += m_fItemHeight; + } + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM htem = pData->GetItem(m_pInterface, i); + GetItemSize(fs, htem, fWidth, m_fItemHeight, bAutoSize); + } + } + if (bAutoSize) { + return fs; + } + FX_FLOAT iWidth = m_rtClient.width - rtUIMargin.left - rtUIMargin.width; + FX_FLOAT iHeight = m_rtClient.height; + FX_BOOL bShowVertScr = + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) && + (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll); + FX_BOOL bShowHorzScr = + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) && + (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll); + if (!bShowVertScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll && + (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) == 0) { + bShowVertScr = (fs.y > iHeight); + } + if (!bShowHorzScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) { + bShowHorzScr = (fs.x > iWidth); + } + CFX_SizeF szRange; + if (bShowVertScr) { + if (!m_pVertScrollBar) { + InitScrollBar(); + } + CFX_RectF rtScrollBar; + rtScrollBar.Set(m_rtClient.right() - m_fScorllBarWidth, m_rtClient.top, + m_fScorllBarWidth, m_rtClient.height - 1); + if (bShowHorzScr) { + rtScrollBar.height -= m_fScorllBarWidth; + } + m_pVertScrollBar->SetWidgetRect(rtScrollBar); + szRange.x = 0, szRange.y = fs.y - m_rtConent.height; + if (szRange.y < m_fItemHeight) { + szRange.y = m_fItemHeight; + } + m_pVertScrollBar->SetRange(szRange.x, szRange.y); + m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10); + m_pVertScrollBar->SetStepSize(m_fItemHeight); + FX_FLOAT fPos = m_pVertScrollBar->GetPos(); + if (fPos < 0) { + fPos = 0; + } + if (fPos > szRange.y) { + fPos = szRange.y; + } + m_pVertScrollBar->SetPos(fPos); + m_pVertScrollBar->SetTrackPos(fPos); + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) == + 0 || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) { + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); + } + m_pVertScrollBar->Update(); + } else if (m_pVertScrollBar) { + m_pVertScrollBar->SetPos(0); + m_pVertScrollBar->SetTrackPos(0); + m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } + if (bShowHorzScr) { + if (!m_pHorzScrollBar) { + InitScrollBar(FALSE); + } + CFX_RectF rtScrollBar; + rtScrollBar.Set(m_rtClient.left, m_rtClient.bottom() - m_fScorllBarWidth, + m_rtClient.width, m_fScorllBarWidth); + if (bShowVertScr) { + rtScrollBar.width -= m_fScorllBarWidth; + } + m_pHorzScrollBar->SetWidgetRect(rtScrollBar); + szRange.x = 0, szRange.y = fs.x - rtScrollBar.width; + m_pHorzScrollBar->SetRange(szRange.x, szRange.y); + m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10); + m_pHorzScrollBar->SetStepSize(fWidth / 10); + FX_FLOAT fPos = m_pHorzScrollBar->GetPos(); + if (fPos < 0) { + fPos = 0; + } + if (fPos > szRange.y) { + fPos = szRange.y; + } + m_pHorzScrollBar->SetPos(fPos); + m_pHorzScrollBar->SetTrackPos(fPos); + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) == + 0 || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) { + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); + } + m_pHorzScrollBar->Update(); + } else if (m_pHorzScrollBar) { + m_pHorzScrollBar->SetPos(0); + m_pHorzScrollBar->SetTrackPos(0); + m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); + } + if (bShowVertScr && bShowHorzScr) { + m_rtStatic.Set(m_rtClient.right() - m_fScorllBarWidth, + m_rtClient.bottom() - m_fScorllBarWidth, m_fScorllBarWidth, + m_fScorllBarWidth); + } + return fs; +} +void CFWL_ListBoxImp::GetItemSize(CFX_SizeF& size, + FWL_HLISTITEM hItem, + FX_FLOAT fWidth, + FX_FLOAT m_fItemHeight, + FX_BOOL bAutoSize) { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) { + } else { + if (!bAutoSize) { + CFX_RectF rtItem; + rtItem.Set(0, size.y, fWidth, m_fItemHeight); + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + pData->SetItemRect(m_pInterface, hItem, rtItem); + } + size.x = fWidth; + size.y += m_fItemHeight; + } +} +FX_FLOAT CFWL_ListBoxImp::GetMaxTextWidth() { + FX_FLOAT fRet = 0.0f; + IFWL_ListBoxDP* pData = + static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); + int32_t iCount = pData->CountItems(m_pInterface); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); + if (!hItem) { + continue; + } + CFX_WideString wsText; + pData->GetItemText(m_pInterface, hItem, wsText); + CFX_SizeF sz = CalcTextSize(wsText, m_pProperties->m_pThemeProvider); + if (sz.x > fRet) { + fRet = sz.x; + } + } + return fRet; +} +FX_FLOAT CFWL_ListBoxImp::GetScrollWidth() { + FX_FLOAT* pfWidth = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pfWidth) + return 0; + return *pfWidth; +} +FX_FLOAT CFWL_ListBoxImp::GetItemHeigt() { + FX_FLOAT* pfFont = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FontSize)); + if (!pfFont) + return 20; + return *pfFont + 2 * FWL_LISTBOX_ItemTextMargin; +} +void CFWL_ListBoxImp::InitScrollBar(FX_BOOL bVert) { + if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) { + return; + } + CFWL_WidgetImpProperties prop; + prop.m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz; + prop.m_dwStates = FWL_WGTSTATE_Invisible; + prop.m_pParent = m_pInterface; + prop.m_pThemeProvider = m_pScrollBarTP; + IFWL_ScrollBar* pScrollBar = IFWL_ScrollBar::Create(prop, m_pInterface); + pScrollBar->Initialize(); + (bVert ? &m_pVertScrollBar : &m_pHorzScrollBar)->reset(pScrollBar); +} +void CFWL_ListBoxImp::SortItem() {} +FX_BOOL CFWL_ListBoxImp::IsShowScrollBar(FX_BOOL bVert) { + IFWL_ScrollBar* pScrollbar = + bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get(); + if (!pScrollbar || (pScrollbar->GetStates() & FWL_WGTSTATE_Invisible)) { + return FALSE; + } + return !(m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_LTB_ShowScrollBarFocus) || + (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); +} +void CFWL_ListBoxImp::ProcessSelChanged() { + CFWL_EvtLtbSelChanged selEvent; + selEvent.m_pSrcTarget = m_pInterface; + CFX_Int32Array arrSels; + int32_t iCount = CountSelItems(); + for (int32_t i = 0; i < iCount; i++) { + FWL_HLISTITEM item = GetSelItem(i); + if (item == NULL) { + continue; + } + selEvent.iarraySels.Add(i); + } + DispatchEvent(&selEvent); +} +CFWL_ListBoxImpDelegate::CFWL_ListBoxImpDelegate(CFWL_ListBoxImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_ListBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + if (!m_pOwner->IsEnabled()) { + return 1; + } + FX_DWORD dwMsgCode = pMessage->GetClassID(); + int32_t iRet = 1; + 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; + } + default: {} + } + break; + } + case FWL_MSGHASH_MouseWheel: { + OnMouseWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage)); + break; + } + case FWL_MSGHASH_Key: { + CFWL_MsgKey* pMsg = static_cast<CFWL_MsgKey*>(pMessage); + if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown) + OnKeyDown(pMsg); + break; + } + default: { iRet = 0; } + } + CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); + return iRet; +} +FWL_ERR CFWL_ListBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + if (!pEvent) + return FWL_ERR_Indefinite; + if (pEvent->GetClassID() != FWL_EVTHASH_Scroll) { + return FWL_ERR_Succeeded; + } + IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget; + if ((pSrcTarget == m_pOwner->m_pVertScrollBar.get() && + m_pOwner->m_pVertScrollBar) || + (pSrcTarget == m_pOwner->m_pHorzScrollBar.get() && + m_pOwner->m_pHorzScrollBar)) { + CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); + OnScroll(static_cast<IFWL_ScrollBar*>(pSrcTarget), + pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos); + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ListBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_ListBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet) { + if (m_pOwner->GetStylesEx() & FWL_STYLEEXT_LTB_ShowScrollBarFocus) { + if (m_pOwner->m_pVertScrollBar) { + m_pOwner->m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet); + } + if (m_pOwner->m_pHorzScrollBar) { + m_pOwner->m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, !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_ListBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + m_pOwner->m_bLButtonDown = TRUE; + if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + m_pOwner->SetFocus(TRUE); + } + FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); + if (!hItem) { + return; + } + if (m_pOwner->m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_LTB_MultiSelection) { + if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) { + FX_BOOL bSelected = m_pOwner->IsItemSelected(hItem); + m_pOwner->SetSelectionDirect(hItem, !bSelected); + m_pOwner->m_hAnchor = hItem; + } else if (pMsg->m_dwFlags & FWL_KEYFLAG_Shift) { + if (m_pOwner->m_hAnchor) { + m_pOwner->SetSelection(m_pOwner->m_hAnchor, hItem, TRUE); + } else { + m_pOwner->SetSelectionDirect(hItem, TRUE); + } + } else { + m_pOwner->SetSelection(hItem, hItem, TRUE); + m_pOwner->m_hAnchor = hItem; + } + } else { + m_pOwner->SetSelection(hItem, hItem, TRUE); + } + if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check) { + FWL_HLISTITEM hSelectedItem = + m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); + CFX_RectF rtCheck; + m_pOwner->GetItemCheckRect(hSelectedItem, rtCheck); + FX_BOOL bChecked = m_pOwner->GetItemChecked(hItem); + if (rtCheck.Contains(pMsg->m_fx, pMsg->m_fy)) { + if (bChecked) { + m_pOwner->SetItemChecked(hItem, FALSE); + } else { + m_pOwner->SetItemChecked(hItem, TRUE); + } + m_pOwner->Update(); + } + } + m_pOwner->SetFocusItem(hItem); + m_pOwner->ScrollToVisible(hItem); + m_pOwner->SetGrab(TRUE); + m_pOwner->ProcessSelChanged(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_ListBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_bLButtonDown) { + m_pOwner->m_bLButtonDown = FALSE; + m_pOwner->SetGrab(FALSE); + DispatchSelChangedEv(); + } +} +void CFWL_ListBoxImpDelegate::OnMouseWheel(CFWL_MsgMouseWheel* pMsg) { + if (!m_pOwner->IsShowScrollBar(TRUE)) { + return; + } + IFWL_WidgetDelegate* pDelegate = + m_pOwner->m_pVertScrollBar->SetDelegate(NULL); + pDelegate->OnProcessMessage(pMsg); +} +void CFWL_ListBoxImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) { + FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; + switch (dwKeyCode) { + case FWL_VKEY_Tab: + case FWL_VKEY_Up: + case FWL_VKEY_Down: + case FWL_VKEY_Home: + case FWL_VKEY_End: { + FWL_HLISTITEM hItem = m_pOwner->GetFocusedItem(); + hItem = m_pOwner->GetItem(hItem, dwKeyCode); + FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift; + FX_BOOL bCtrl = pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl; + OnVK(hItem, bShift, bCtrl); + DispatchSelChangedEv(); + m_pOwner->ProcessSelChanged(); + break; + } + default: {} + } +} +void CFWL_ListBoxImpDelegate::OnVK(FWL_HLISTITEM hItem, + FX_BOOL bShift, + FX_BOOL bCtrl) { + if (!hItem) { + return; + } + if (m_pOwner->m_pProperties->m_dwStyleExes & + FWL_STYLEEXT_LTB_MultiSelection) { + if (bCtrl) { + } else if (bShift) { + if (m_pOwner->m_hAnchor) { + m_pOwner->SetSelection(m_pOwner->m_hAnchor, hItem, TRUE); + } else { + m_pOwner->SetSelectionDirect(hItem, TRUE); + } + } else { + m_pOwner->SetSelection(hItem, hItem, TRUE); + m_pOwner->m_hAnchor = hItem; + } + } else { + m_pOwner->SetSelection(hItem, hItem, TRUE); + } + m_pOwner->SetFocusItem(hItem); + m_pOwner->ScrollToVisible(hItem); + { + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width, + m_pOwner->m_pProperties->m_rtWidget.height); + m_pOwner->Repaint(&rtInvalidate); + } +} +FX_BOOL CFWL_ListBoxImpDelegate::OnScroll(IFWL_ScrollBar* pScrollBar, + FX_DWORD dwCode, + FX_FLOAT fPos) { + CFX_SizeF fs; + pScrollBar->GetRange(fs.x, fs.y); + FX_FLOAT iCurPos = pScrollBar->GetPos(); + FX_FLOAT fStep = pScrollBar->GetStepSize(); + switch (dwCode) { + case FWL_SCBCODE_Min: { + fPos = fs.x; + break; + } + case FWL_SCBCODE_Max: { + fPos = fs.y; + break; + } + case FWL_SCBCODE_StepBackward: { + fPos -= fStep; + if (fPos < fs.x + fStep / 2) { + fPos = fs.x; + } + break; + } + case FWL_SCBCODE_StepForward: { + fPos += fStep; + if (fPos > fs.y - fStep / 2) { + fPos = fs.y; + } + break; + } + case FWL_SCBCODE_PageBackward: { + fPos -= pScrollBar->GetPageSize(); + if (fPos < fs.x) { + fPos = fs.x; + } + break; + } + case FWL_SCBCODE_PageForward: { + fPos += pScrollBar->GetPageSize(); + if (fPos > fs.y) { + fPos = fs.y; + } + break; + } + case FWL_SCBCODE_Pos: + case FWL_SCBCODE_TrackPos: + break; + case FWL_SCBCODE_EndScroll: + return FALSE; + } + if (iCurPos != fPos) { + pScrollBar->SetPos(fPos); + pScrollBar->SetTrackPos(fPos); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + return TRUE; +} +void CFWL_ListBoxImpDelegate::DispatchSelChangedEv() { + CFWL_EvtLtbSelChanged ev; + ev.m_pSrcTarget = m_pOwner->m_pInterface; + m_pOwner->DispatchEvent(&ev); +} diff --git a/xfa/src/fwl/basewidget/fwl_listboximp.h b/xfa/src/fwl/basewidget/fwl_listboximp.h new file mode 100644 index 0000000000..614b76c495 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_listboximp.h @@ -0,0 +1,121 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_LISTBOXIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_LISTBOXIMP_H_ + +#include <memory> + +#include "xfa/include/fwl/basewidget/fwl_combobox.h" +#include "xfa/include/fwl/basewidget/fwl_edit.h" +#include "xfa/include/fwl/basewidget/fwl_listbox.h" +#include "xfa/include/fwl/basewidget/fwl_scrollbar.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_ListBoxImpDelegate; + +class CFWL_ListBoxImp : public CFWL_WidgetImp { + public: + CFWL_ListBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_ListBoxImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FX_DWORD HitTest(FX_FLOAT fx, FX_FLOAT fy); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual FWL_ERR SetThemeProvider(IFWL_ThemeProvider* pThemeProvider); + virtual int32_t CountSelItems(); + virtual FWL_HLISTITEM GetSelItem(int32_t nIndexSel); + virtual int32_t GetSelIndex(int32_t nIndex); + virtual FWL_ERR SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect = TRUE); + virtual FWL_ERR GetItemText(FWL_HLISTITEM hItem, CFX_WideString& wsText); + virtual FWL_ERR GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert = TRUE); + virtual FWL_ERR* Sort(IFWL_ListBoxCompare* pCom); + + protected: + FWL_HLISTITEM GetItem(FWL_HLISTITEM hItem, FX_DWORD dwKeyCode); + void SetSelection(FWL_HLISTITEM hStart, + FWL_HLISTITEM hEnd, + FX_BOOL bSelected); + void SetSelectionDirect(FWL_HLISTITEM hItem, FX_BOOL bSelect); + FX_BOOL IsItemSelected(FWL_HLISTITEM hItem); + void ClearSelection(); + void SelectAll(); + FWL_HLISTITEM GetFocusedItem(); + void SetFocusItem(FWL_HLISTITEM hItem); + FWL_HLISTITEM GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy); + FX_BOOL GetItemCheckRect(FWL_HLISTITEM hItem, CFX_RectF& rtCheck); + FX_BOOL SetItemChecked(FWL_HLISTITEM hItem, FX_BOOL bChecked); + FX_BOOL GetItemChecked(FWL_HLISTITEM hItem); + FX_BOOL ScrollToVisible(FWL_HLISTITEM hItem); + void DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix = NULL); + void DrawItems(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix = NULL); + void DrawItem(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + FWL_HLISTITEM hItem, + int32_t Index, + const CFX_RectF& rtItem, + const CFX_Matrix* pMatrix = NULL); + void DrawStatic(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme); + CFX_SizeF CalcSize(FX_BOOL bAutoSize = FALSE); + void GetItemSize(CFX_SizeF& size, + FWL_HLISTITEM hItem, + FX_FLOAT fWidth, + FX_FLOAT fHeight, + FX_BOOL bAutoSize = FALSE); + FX_FLOAT GetMaxTextWidth(); + FX_FLOAT GetScrollWidth(); + FX_FLOAT GetItemHeigt(); + void InitScrollBar(FX_BOOL bVert = TRUE); + void SortItem(); + FX_BOOL IsShowScrollBar(FX_BOOL bVert); + void ProcessSelChanged(); + + protected: + CFX_RectF m_rtClient; + CFX_RectF m_rtStatic; + CFX_RectF m_rtConent; + std::unique_ptr<IFWL_ScrollBar> m_pHorzScrollBar; + std::unique_ptr<IFWL_ScrollBar> m_pVertScrollBar; + FX_DWORD m_dwTTOStyles; + int32_t m_iTTOAligns; + FWL_HLISTITEM m_hAnchor; + FX_FLOAT m_fItemHeight; + FX_FLOAT m_fScorllBarWidth; + FX_BOOL m_bLButtonDown; + IFWL_ThemeProvider* m_pScrollBarTP; + friend class CFWL_ListBoxImpDelegate; +}; +class CFWL_ListBoxImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_ListBoxImpDelegate(CFWL_ListBoxImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseWheel(CFWL_MsgMouseWheel* pMsg); + void OnKeyDown(CFWL_MsgKey* pMsg); + void OnVK(FWL_HLISTITEM hItem, FX_BOOL bShift, FX_BOOL bCtrl); + FX_BOOL OnScroll(IFWL_ScrollBar* pScrollBar, FX_DWORD dwCode, FX_FLOAT fPos); + void DispatchSelChangedEv(); + CFWL_ListBoxImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_LISTBOXIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_monthcalendarimp.cpp b/xfa/src/fwl/basewidget/fwl_monthcalendarimp.cpp new file mode 100644 index 0000000000..102f225a1d --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_monthcalendarimp.cpp @@ -0,0 +1,1098 @@ +// 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/src/fwl/basewidget/fwl_monthcalendarimp.h" + +#include <algorithm> + +#include "xfa/include/fwl/basewidget/fwl_monthcalendar.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fdp/include/fde_tto.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +#define MONTHCAL_HSEP_HEIGHT 1 +#define MONTHCAL_VSEP_WIDTH 1 +#define MONTHCAL_HMARGIN 3 +#define MONTHCAL_VMARGIN 2 +#define MONTHCAL_ROWS 9 +#define MONTHCAL_COLUMNS 7 +#define MONTHCAL_HEADER_BTN_VMARGIN 7 +#define MONTHCAL_HEADER_BTN_HMARGIN 5 + +// static +IFWL_MonthCalendar* IFWL_MonthCalendar::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_MonthCalendar* pMonthCalendar = new IFWL_MonthCalendar; + CFWL_MonthCalendarImp* pMonthCalendarImpl = + new CFWL_MonthCalendarImp(properties, pOuter); + pMonthCalendar->SetImpl(pMonthCalendarImpl); + pMonthCalendarImpl->SetInterface(pMonthCalendar); + return pMonthCalendar; +} +IFWL_MonthCalendar::IFWL_MonthCalendar() {} +int32_t IFWL_MonthCalendar::CountSelect() { + return static_cast<CFWL_MonthCalendarImp*>(GetImpl())->CountSelect(); +} +FX_BOOL IFWL_MonthCalendar::GetSelect(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay, + int32_t nIndex) { + return static_cast<CFWL_MonthCalendarImp*>(GetImpl()) + ->GetSelect(iYear, iMonth, iDay, nIndex); +} +FX_BOOL IFWL_MonthCalendar::SetSelect(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + return static_cast<CFWL_MonthCalendarImp*>(GetImpl()) + ->SetSelect(iYear, iMonth, iDay); +} + +CFWL_MonthCalendarImp::CFWL_MonthCalendarImp( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_iCurYear(2011), + m_iCurMonth(1), + m_iYear(2011), + m_iMonth(1), + m_iDay(1), + m_iHovered(-1), + m_iLBtnPartStates(FWL_PARTSTATE_MCD_Normal), + m_iRBtnPartStates(FWL_PARTSTATE_MCD_Normal) { + m_rtHead.Reset(); + m_rtWeek.Reset(); + m_rtLBtn.Reset(); + m_rtRBtn.Reset(); + m_rtDates.Reset(); + m_rtHSep.Reset(); + m_rtHeadText.Reset(); + m_rtToday.Reset(); + m_rtTodayFlag.Reset(); + m_rtClient.Reset(); + m_rtWeekNum.Reset(); + m_rtWeekNumSep.Reset(); + m_pDateTime = new CFX_DateTime; + m_bInit = FALSE; + m_iMaxSel = 1; +} +CFWL_MonthCalendarImp::~CFWL_MonthCalendarImp() { + ClearDateItem(); + delete m_pDateTime; + m_arrSelDays.RemoveAll(); +} +FWL_ERR CFWL_MonthCalendarImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_MonthCalendar; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_MonthCalendarImp::GetClassID() const { + return FWL_CLASSHASH_MonthCalendar; +} +FWL_ERR CFWL_MonthCalendarImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_MonthCalendarImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_MonthCalendarImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_MonthCalendarImp::GetWidgetRect(CFX_RectF& rect, + FX_BOOL bAutoSize) { + if (bAutoSize) { + CFX_SizeF fs = CalcSize(TRUE); + rect.Set(0, 0, fs.x, fs.y); + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_MonthCalendarImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + GetCapValue(); + if (!m_bInit) { + m_bInit = InitDate(); + } + ClearDateItem(); + ReSetDateItem(); + LayOut(); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_MonthCalendarImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (m_pProperties->m_pThemeProvider == NULL) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_MCD_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_MCD_Edge, pTheme, pMatrix); + } + DrawBkground(pGraphics, pTheme, pMatrix); + DrawHeadBK(pGraphics, pTheme, pMatrix); + DrawLButton(pGraphics, pTheme, pMatrix); + DrawRButton(pGraphics, pTheme, pMatrix); + DrawSeperator(pGraphics, pTheme, pMatrix); + DrawDatesInBK(pGraphics, pTheme, pMatrix); + DrawDatesInCircle(pGraphics, pTheme, pMatrix); + DrawCaption(pGraphics, pTheme, pMatrix); + DrawWeek(pGraphics, pTheme, pMatrix); + DrawDatesIn(pGraphics, pTheme, pMatrix); + DrawDatesOut(pGraphics, pTheme, pMatrix); + DrawToday(pGraphics, pTheme, pMatrix); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_WeekNumbers) { + DrawWeekNumberSep(pGraphics, pTheme, pMatrix); + DrawWeekNumber(pGraphics, pTheme, pMatrix); + } + return FWL_ERR_Succeeded; +} +int32_t CFWL_MonthCalendarImp::CountSelect() { + return m_arrSelDays.GetSize(); +} +FX_BOOL CFWL_MonthCalendarImp::GetSelect(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay, + int32_t nIndex) { + if (nIndex >= m_arrSelDays.GetSize()) { + return FALSE; + } + iYear = m_iCurYear; + iMonth = m_iCurMonth; + iDay = m_arrSelDays[nIndex]; + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::SetSelect(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + ChangeToMonth(iYear, iMonth); + return AddSelDay(iDay); +} +void CFWL_MonthCalendarImp::DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_Background; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_rtPart = m_rtClient; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawHeadBK(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_Header; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_rtPart = m_rtHead; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawLButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_LBtn; + params.m_pGraphics = pGraphics; + params.m_dwStates = m_iLBtnPartStates; + params.m_rtPart = m_rtLBtn; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawRButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_RBtn; + params.m_pGraphics = pGraphics; + params.m_dwStates = m_iRBtnPartStates; + params.m_rtPart = m_rtRBtn; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawCaption(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeText textParam; + textParam.m_pWidget = m_pInterface; + textParam.m_iPart = FWL_PART_MCD_Caption; + textParam.m_dwStates = FWL_PARTSTATE_MCD_Normal; + textParam.m_pGraphics = pGraphics; + int32_t iYear; + int32_t iMonth; + iYear = m_iCurYear; + iMonth = m_iCurMonth; + CFX_WideString wsCation; + GetHeadText(iYear, iMonth, wsCation); + textParam.m_wsText = wsCation; + m_szHead = CalcTextSize(textParam.m_wsText, m_pProperties->m_pThemeProvider); + CalcHeadSize(); + textParam.m_rtPart = m_rtHeadText; + textParam.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + textParam.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + if (pMatrix) { + textParam.m_matrix.Concat(*pMatrix); + } + pTheme->DrawText(&textParam); +} +void CFWL_MonthCalendarImp::DrawSeperator(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_HSeparator; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_rtPart = m_rtHSep; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawDatesInBK(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_DateInBK; + params.m_pGraphics = pGraphics; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + int32_t iCount = m_arrDates.GetSize(); + for (int32_t j = 0; j < iCount; j++) { + FWL_DATEINFO* pDataInfo = (FWL_DATEINFO*)m_arrDates.GetAt(j); + if (pDataInfo->dwStates & FWL_ITEMSTATE_MCD_Selected) { + params.m_dwStates |= FWL_PARTSTATE_MCD_Selected; + if (((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoTodayCircle) == + 0) && + pDataInfo->dwStates & FWL_ITEMSTATE_MCD_Flag) { + params.m_dwStates |= FWL_PARTSTATE_MCD_Flagged; + } + if (pDataInfo->dwStates & FWL_ITEMSTATE_MCD_Focused) { + params.m_dwStates |= FWL_PARTSTATE_MCD_Focused; + } + } else if (j == m_iHovered - 1) { + params.m_dwStates |= FWL_PARTSTATE_MCD_Hovered; + } else if (pDataInfo->dwStates & FWL_ITEMSTATE_MCD_Flag) { + params.m_dwStates = FWL_PARTSTATE_MCD_Flagged; + pTheme->DrawBackground(¶ms); + } + params.m_rtPart = pDataInfo->rect; + pTheme->DrawBackground(¶ms); + params.m_dwStates = 0; + } +} +void CFWL_MonthCalendarImp::DrawWeek(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeText params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_Week; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + CFX_RectF rtDayOfWeek; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + for (int32_t i = 0; i < 7; i++) { + rtDayOfWeek.Set(m_rtWeek.left + i * (m_szCell.x + MONTHCAL_HMARGIN * 2), + m_rtWeek.top, m_szCell.x, m_szCell.y); + CFX_WideString* wsWeekDay = static_cast<CFX_WideString*>( + pTheme->GetCapacity(¶ms, i + FWL_MCCAPACITY_Sun)); + params.m_rtPart = rtDayOfWeek; + params.m_wsText = *wsWeekDay; + params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + pTheme->DrawText(¶ms); + } +} +void CFWL_MonthCalendarImp::DrawWeekNumber(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeText params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_WeekNum; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + CFX_WideString wsWeekNum; + params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + int32_t iWeekNum = 0; + int32_t iMonthNum = m_pDateTime->GetMonth(); + int32_t iDayNum = FX_DaysInMonth(m_iCurYear, iMonthNum); + int32_t iTemp = 0; + FX_FLOAT fVStartPos = m_rtClient.top + m_fHeadHei + m_fHSepHei; + FX_FLOAT fHStartPos = m_rtClient.left; + for (int32_t i = 1; i <= iDayNum; i += 7) { + iTemp++; + iWeekNum = CalWeekNumber(m_iCurYear, iMonthNum, i); + m_rtWeekNum.Set(fHStartPos, fVStartPos + m_fDateCellHei * iTemp, + m_fWeekNumWid, m_fDateCellHei); + wsWeekNum.Format(L"%d", iWeekNum); + params.m_wsText = wsWeekNum; + params.m_rtPart = m_rtWeekNum; + pTheme->DrawText(¶ms); + } +} +void CFWL_MonthCalendarImp::DrawWeekNumberSep(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_WeekNumSep; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_rtPart = m_rtWeekNumSep; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawToday(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoToday) { + return; + } + CFWL_ThemeText params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_Today; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + CFX_WideString* wsDay = static_cast<CFX_WideString*>( + pTheme->GetCapacity(¶ms, FWL_MCCAPACITY_Today)); + CFX_WideString wsText; + GetTodayText(m_iYear, m_iMonth, m_iDay, wsText); + params.m_wsText = *wsDay + wsText; + m_szToday = CalcTextSize(params.m_wsText, m_pProperties->m_pThemeProvider); + CalcTodaySize(); + params.m_rtPart = m_rtToday; + params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawText(¶ms); +} +void CFWL_MonthCalendarImp::DrawDatesIn(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeText params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_DatesIn; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + int32_t iCount = m_arrDates.GetSize(); + for (int32_t j = 0; j < iCount; j++) { + FWL_DATEINFO* pDataInfo = (FWL_DATEINFO*)m_arrDates.GetAt(j); + params.m_wsText = pDataInfo->wsDay; + params.m_rtPart = pDataInfo->rect; + params.m_dwStates = pDataInfo->dwStates; + if (j + 1 == m_iHovered) { + params.m_dwStates |= FWL_PARTSTATE_MCD_Hovered; + } + params.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + pTheme->DrawText(¶ms); + } +} +void CFWL_MonthCalendarImp::DrawDatesOut(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeText params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_DatesOut; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_iTTOAlign = FDE_TTOALIGNMENT_Center; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawText(¶ms); +} +void CFWL_MonthCalendarImp::DrawDatesInCircle(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoTodayCircle) { + return; + } + if (m_iMonth != m_iCurMonth || m_iYear != m_iCurYear) { + return; + } + if (m_iDay < 1 || m_iDay > m_arrDates.GetSize()) { + return; + } + FWL_DATEINFO* pDate = (FWL_DATEINFO*)m_arrDates[m_iDay - 1]; + if (!pDate) + return; + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_DateInCircle; + params.m_pGraphics = pGraphics; + params.m_rtPart = pDate->rect; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +void CFWL_MonthCalendarImp::DrawTodayCircle(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoToday) { + return; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoTodayCircle) { + return; + } + CFWL_ThemeBackground params; + params.m_pWidget = m_pInterface; + params.m_iPart = FWL_PART_MCD_TodayCircle; + params.m_pGraphics = pGraphics; + params.m_dwStates = FWL_PARTSTATE_MCD_Normal; + params.m_rtPart = m_rtTodayFlag; + if (pMatrix) { + params.m_matrix.Concat(*pMatrix); + } + pTheme->DrawBackground(¶ms); +} +CFX_SizeF CFWL_MonthCalendarImp::CalcSize(FX_BOOL bAutoSize) { + if (!m_pProperties->m_pThemeProvider) + return CFX_SizeF(); + + if (!bAutoSize) { + GetClientRect(m_rtClient); + return CFX_SizeF(m_rtClient.width, m_rtClient.height); + } + + CFX_SizeF fs; + CFWL_ThemePart params; + params.m_pWidget = m_pInterface; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + CFX_WideString* wsText = NULL; + FX_FLOAT fMaxWeekW = 0.0f; + FX_FLOAT fMaxWeekH = 0.0f; + for (FX_DWORD week = FWL_MCCAPACITY_Sun; week <= FWL_MCCAPACITY_Sat; week++) { + wsText = static_cast<CFX_WideString*>(pTheme->GetCapacity(¶ms, week)); + CFX_SizeF sz = CalcTextSize(*wsText, m_pProperties->m_pThemeProvider); + fMaxWeekW = (fMaxWeekW >= sz.x) ? fMaxWeekW : sz.x; + fMaxWeekH = (fMaxWeekH >= sz.y) ? fMaxWeekH : sz.y; + } + FX_FLOAT fDayMaxW = 0.0f; + FX_FLOAT fDayMaxH = 0.0f; + for (int day = 10; day <= 31; day++) { + CFX_WideString wsDay; + wsDay.Format(L"%d", day); + CFX_SizeF sz = CalcTextSize(wsDay, m_pProperties->m_pThemeProvider); + fDayMaxW = (fDayMaxW >= sz.x) ? fDayMaxW : sz.x; + fDayMaxH = (fDayMaxH >= sz.y) ? fDayMaxH : sz.y; + } + m_szCell.x = FX_FLOAT((fMaxWeekW >= fDayMaxW) ? (int)(fMaxWeekW + 0.5) + : (int)(fDayMaxW + 0.5)); + m_szCell.y = (fMaxWeekH >= fDayMaxH) ? fMaxWeekH : fDayMaxH; + fs.x = m_szCell.x * MONTHCAL_COLUMNS + + MONTHCAL_HMARGIN * MONTHCAL_COLUMNS * 2 + + MONTHCAL_HEADER_BTN_HMARGIN * 2; + FX_FLOAT fMonthMaxW = 0.0f; + FX_FLOAT fMonthMaxH = 0.0f; + for (FX_DWORD month = FWL_MCCAPACITY_January; + month <= FWL_MCCAPACITY_December; month++) { + wsText = static_cast<CFX_WideString*>(pTheme->GetCapacity(¶ms, month)); + CFX_SizeF sz = CalcTextSize(*wsText, m_pProperties->m_pThemeProvider); + fMonthMaxW = (fMonthMaxW >= sz.x) ? fMonthMaxW : sz.x; + fMonthMaxH = (fMonthMaxH >= sz.y) ? fMonthMaxH : sz.y; + } + CFX_WideString wsYear; + GetHeadText(m_iYear, m_iMonth, wsYear); + CFX_SizeF szYear = CalcTextSize(wsYear, m_pProperties->m_pThemeProvider); + fMonthMaxH = std::max(fMonthMaxH, szYear.y); + m_szHead = CFX_SizeF(fMonthMaxW + szYear.x, fMonthMaxH); + fMonthMaxW = m_szHead.x + MONTHCAL_HEADER_BTN_HMARGIN * 2 + m_szCell.x * 2; + fs.x = std::max(fs.x, fMonthMaxW); + CFX_WideString wsToday; + GetTodayText(m_iYear, m_iMonth, m_iDay, wsToday); + wsText = static_cast<CFX_WideString*>( + pTheme->GetCapacity(¶ms, FWL_MCCAPACITY_Today)); + m_wsToday = *wsText + wsToday; + m_szToday = CalcTextSize(wsToday, m_pProperties->m_pThemeProvider); + m_szToday.y = (m_szToday.y >= m_szCell.y) ? m_szToday.y : m_szCell.y; + fs.y = m_szCell.x + m_szCell.y * (MONTHCAL_ROWS - 2) + m_szToday.y + + MONTHCAL_VMARGIN * MONTHCAL_ROWS * 2 + MONTHCAL_HEADER_BTN_VMARGIN * 4; + return fs; +} + +void CFWL_MonthCalendarImp::CalcHeadSize() { + FX_FLOAT fHeadHMargin = (m_rtClient.width - m_szHead.x) / 2; + FX_FLOAT fHeadVMargin = (m_szCell.x - m_szHead.y) / 2; + m_rtHeadText.Set(m_rtClient.left + fHeadHMargin, + m_rtClient.top + MONTHCAL_HEADER_BTN_VMARGIN + + MONTHCAL_VMARGIN + fHeadVMargin, + m_szHead.x, m_szHead.y); +} +void CFWL_MonthCalendarImp::CalcTodaySize() { + m_rtTodayFlag.Set( + m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN + MONTHCAL_HMARGIN, + m_rtDates.bottom() + MONTHCAL_HEADER_BTN_VMARGIN + MONTHCAL_VMARGIN, + m_szCell.x, m_szToday.y); + m_rtToday.Set( + m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN + m_szCell.x + + MONTHCAL_HMARGIN * 2, + m_rtDates.bottom() + MONTHCAL_HEADER_BTN_VMARGIN + MONTHCAL_VMARGIN, + m_szToday.x, m_szToday.y); +} +void CFWL_MonthCalendarImp::LayOut() { + GetClientRect(m_rtClient); + { + m_rtHead.Set( + m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN, m_rtClient.top, + m_rtClient.width - MONTHCAL_HEADER_BTN_HMARGIN * 2, + m_szCell.x + (MONTHCAL_HEADER_BTN_VMARGIN + MONTHCAL_VMARGIN) * 2); + m_rtWeek.Set(m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN, + m_rtHead.bottom(), + m_rtClient.width - MONTHCAL_HEADER_BTN_HMARGIN * 2, + m_szCell.y + MONTHCAL_VMARGIN * 2); + m_rtLBtn.Set(m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN, + m_rtClient.top + MONTHCAL_HEADER_BTN_VMARGIN, m_szCell.x, + m_szCell.x); + m_rtRBtn.Set(m_rtClient.left + m_rtClient.width - + MONTHCAL_HEADER_BTN_HMARGIN - m_szCell.x, + m_rtClient.top + MONTHCAL_HEADER_BTN_VMARGIN, m_szCell.x, + m_szCell.x); + m_rtHSep.Set( + m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN + MONTHCAL_HMARGIN, + m_rtWeek.bottom() - MONTHCAL_VMARGIN, + m_rtClient.width - (MONTHCAL_HEADER_BTN_HMARGIN + MONTHCAL_HMARGIN) * 2, + MONTHCAL_HSEP_HEIGHT); + m_rtDates.Set(m_rtClient.left + MONTHCAL_HEADER_BTN_HMARGIN, + m_rtWeek.bottom(), + m_rtClient.width - MONTHCAL_HEADER_BTN_HMARGIN * 2, + m_szCell.y * (MONTHCAL_ROWS - 3) + + MONTHCAL_VMARGIN * (MONTHCAL_ROWS - 3) * 2); + } + CalDateItem(); +} +void CFWL_MonthCalendarImp::CalDateItem() { + FX_BOOL bNewWeek = FALSE; + int32_t iWeekOfMonth = 0; + FX_FLOAT fLeft = m_rtDates.left; + FX_FLOAT fTop = m_rtDates.top; + int32_t iCount = m_arrDates.GetSize(); + for (int32_t i = 0; i < iCount; i++) { + FWL_DATEINFO* pDateInfo = (FWL_DATEINFO*)m_arrDates.GetAt(i); + if (bNewWeek) { + iWeekOfMonth++; + bNewWeek = FALSE; + } + pDateInfo->rect.Set( + fLeft + pDateInfo->iDayOfWeek * (m_szCell.x + (MONTHCAL_HMARGIN * 2)), + fTop + iWeekOfMonth * (m_szCell.y + (MONTHCAL_VMARGIN * 2)), + m_szCell.x + (MONTHCAL_HMARGIN * 2), + m_szCell.y + (MONTHCAL_VMARGIN * 2)); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_WeekNumbers) { + pDateInfo->rect.Offset(m_fWeekNumWid, 0); + } + if (pDateInfo->iDayOfWeek >= 6) { + bNewWeek = TRUE; + } + } +} +void CFWL_MonthCalendarImp::GetCapValue() { + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + CFWL_ThemePart part; + part.m_pWidget = m_pInterface; + m_fHeadWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_WIDTH)); + m_fHeadHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_Height)); + m_fHeadBtnWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_BTN_WIDTH)); + m_fHeadBtnHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_BTN_HEIGHT)); + m_fHeadBtnHMargin = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_BTN_HMARGIN)); + m_fHeadBtnVMargin = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_BTN_VMARGIN)); + m_fHeadTextWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_TEXTWIDHT)); + m_fHeadTextHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_TEXTHEIGHT)); + m_fHeadTextHMargin = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_TEXT_HMARGIN)); + m_fHeadTextVMargin = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEADER_TEXT_VMARGIN)); + m_fHSepWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HSEP_WIDTH)); + m_fHSepHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HSEP_HEIGHT)); + m_fWeekNumWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_WEEKNUM_WIDTH)); + m_fSepDOffset = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_SEP_DOFFSET)); + m_fSepX = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_SEP_X)); + m_fSepY = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_SEP_Y)); + m_fWeekNumHeigh = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_WEEKNUM_HEIGHT)); + m_fWeekWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_WEEK_WIDTH)); + m_fWeekHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_WEEK_HEIGHT)); + m_fDateCellWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_DATES_CELL_WIDTH)); + m_fDateCellHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_DATES_CELL_HEIGHT)); + m_fTodayWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_TODAY_WIDHT)); + m_fTodayHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_TODAY_HEIGHT)); + m_fTodayFlagWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_TODAY_FLAG_WIDHT)); + m_fMCWid = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_WIDTH)); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_WeekNumbers) { + m_fMCWid += m_fWeekNumWid; + } + m_fMCHei = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_MC_HEIGHT)); +} +int32_t CFWL_MonthCalendarImp::CalWeekNumber(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + return 0; +} +FX_BOOL CFWL_MonthCalendarImp::GetMinDate(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay) { + iYear = m_dtMin.iYear; + iMonth = m_dtMin.iMonth; + iDay = m_dtMin.iDay; + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::SetMinDate(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + m_dtMin = DATE(iYear, iMonth, iDay); + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::GetMaxDate(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay) { + iYear = m_dtMax.iYear; + iMonth = m_dtMax.iMonth; + iDay = m_dtMax.iDay; + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::SetMaxDate(int32_t iYear, + int32_t iMonth, + int32_t iDay) { + m_dtMax = DATE(iYear, iMonth, iDay); + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::InitDate() { + if (m_pProperties->m_pDataProvider) { + IFWL_MonthCalendarDP* pDateProv = + static_cast<IFWL_MonthCalendarDP*>(m_pProperties->m_pDataProvider); + m_iYear = pDateProv->GetCurYear(m_pInterface); + m_iMonth = pDateProv->GetCurMonth(m_pInterface); + m_iDay = pDateProv->GetCurDay(m_pInterface); + m_iCurYear = m_iYear; + m_iCurMonth = m_iMonth; + } else { + m_iDay = 1; + m_iMonth = 1; + m_iYear = 1; + m_iCurYear = m_iYear; + m_iCurMonth = m_iMonth; + } + GetTodayText(m_iYear, m_iMonth, m_iDay, m_wsToday); + GetHeadText(m_iCurYear, m_iCurMonth, m_wsHead); + m_dtMin = DATE(1500, 12, 1); + m_dtMax = DATE(2200, 1, 1); + return TRUE; +} +void CFWL_MonthCalendarImp::ClearDateItem() { + int32_t iCount = m_arrDates.GetSize(); + for (int32_t i = 0; i < iCount; i++) { + FWL_DATEINFO* pData = (FWL_DATEINFO*)m_arrDates.GetAt(i); + delete pData; + } + m_arrDates.RemoveAll(); +} +void CFWL_MonthCalendarImp::ReSetDateItem() { + m_pDateTime->Set(m_iCurYear, m_iCurMonth, 1); + int32_t iDays = FX_DaysInMonth(m_iCurYear, m_iCurMonth); + int32_t iDayOfWeek = m_pDateTime->GetDayOfWeek(); + for (int32_t i = 0; i < iDays; i++) { + if (iDayOfWeek >= 7) { + iDayOfWeek = 0; + } + CFX_WideString wsDay; + wsDay.Format(L"%d", i + 1); + FX_DWORD dwStates = 0; + if (m_iYear == m_iCurYear && m_iMonth == m_iCurMonth && m_iDay == (i + 1)) { + dwStates |= FWL_ITEMSTATE_MCD_Flag; + } + if (m_arrSelDays.Find(i + 1) != -1) { + dwStates |= FWL_ITEMSTATE_MCD_Selected; + } + CFX_RectF rtDate; + rtDate.Set(0, 0, 0, 0); + m_arrDates.Add( + new FWL_DATEINFO(i + 1, iDayOfWeek, dwStates, rtDate, wsDay)); + iDayOfWeek++; + } +} +FX_BOOL CFWL_MonthCalendarImp::NextMonth() { + int32_t iYear = m_iCurYear, iMonth = m_iCurMonth; + if (iMonth >= 12) { + iMonth = 1; + iYear++; + } else { + iMonth++; + } + DATE dt(m_iCurYear, m_iCurMonth, 1); + if (!(dt < m_dtMax)) { + return FALSE; + } + m_iCurYear = iYear, m_iCurMonth = iMonth; + ChangeToMonth(m_iCurYear, m_iCurMonth); + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::PrevMonth() { + int32_t iYear = m_iCurYear, iMonth = m_iCurMonth; + if (iMonth <= 1) { + iMonth = 12; + iYear--; + } else { + iMonth--; + } + DATE dt(m_iCurYear, m_iCurMonth, 1); + if (!(dt > m_dtMin)) { + return FALSE; + } + m_iCurYear = iYear, m_iCurMonth = iMonth; + ChangeToMonth(m_iCurYear, m_iCurMonth); + return TRUE; +} +void CFWL_MonthCalendarImp::ChangeToMonth(int32_t iYear, int32_t iMonth) { + m_iCurYear = iYear; + m_iCurMonth = iMonth; + m_iHovered = -1; + ClearDateItem(); + ReSetDateItem(); + CalDateItem(); + GetHeadText(m_iCurYear, m_iCurMonth, m_wsHead); +} +FX_BOOL CFWL_MonthCalendarImp::RemoveSelDay(int32_t iDay, FX_BOOL bAll) { + if (iDay == -1 && !bAll) { + return FALSE; + } + if (bAll) { + int32_t iCount = m_arrSelDays.GetSize(); + int32_t iDatesCount = m_arrDates.GetSize(); + for (int32_t i = 0; i < iCount; i++) { + int32_t iSelDay = m_arrSelDays.GetAt(i); + if (iSelDay <= iDatesCount) { + FWL_DATEINFO* pDateInfo = (FWL_DATEINFO*)m_arrDates.GetAt(iSelDay - 1); + pDateInfo->dwStates &= ~FWL_ITEMSTATE_MCD_Selected; + } + } + m_arrSelDays.RemoveAll(); + } else { + int32_t index = m_arrSelDays.Find(iDay); + if (index == -1) { + return FALSE; + } + int32_t iSelDay = m_arrSelDays.GetAt(iDay); + int32_t iDatesCount = m_arrDates.GetSize(); + if (iSelDay <= iDatesCount) { + FWL_DATEINFO* pDateInfo = (FWL_DATEINFO*)m_arrDates.GetAt(iSelDay - 1); + pDateInfo->dwStates &= ~FWL_ITEMSTATE_MCD_Selected; + } + m_arrSelDays.RemoveAt(index); + } + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::AddSelDay(int32_t iDay) { + FXSYS_assert(iDay > 0); + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_MultiSelect) { + } else { + if (m_arrSelDays.Find(iDay) == -1) { + RemoveSelDay(-1, TRUE); + if (iDay <= m_arrDates.GetSize()) { + FWL_DATEINFO* pDateInfo = (FWL_DATEINFO*)m_arrDates.GetAt(iDay - 1); + pDateInfo->dwStates |= FWL_ITEMSTATE_MCD_Selected; + } + m_arrSelDays.Add(iDay); + } + } + return TRUE; +} +FX_BOOL CFWL_MonthCalendarImp::JumpToToday() { + if (m_iYear != m_iCurYear || m_iMonth != m_iCurMonth) { + m_iCurYear = m_iYear; + m_iCurMonth = m_iMonth; + ChangeToMonth(m_iYear, m_iMonth); + AddSelDay(m_iDay); + } else { + if (m_arrSelDays.Find(m_iDay) == -1) { + AddSelDay(m_iDay); + } + } + return TRUE; +} +void CFWL_MonthCalendarImp::GetHeadText(int32_t iYear, + int32_t iMonth, + CFX_WideString& wsHead) { + FXSYS_assert(iMonth > 0 && iMonth < 13); + static const FX_WCHAR* const pMonth[] = { + L"January", L"February", L"March", L"April", + L"May", L"June", L"July", L"August", + L"September", L"October", L"November", L"December"}; + wsHead.Format(L"%s, %d", pMonth[iMonth - 1], iYear); +} +void CFWL_MonthCalendarImp::GetTodayText(int32_t iYear, + int32_t iMonth, + int32_t iDay, + CFX_WideString& wsToday) { + wsToday.Format(L", %d/%d/%d", iDay, iMonth, iYear); +} +int32_t CFWL_MonthCalendarImp::GetDayAtPoint(FX_FLOAT x, FX_FLOAT y) { + int32_t iCount = m_arrDates.GetSize(); + for (int32_t i = 0; i < iCount; i++) { + FWL_DATEINFO* pDateInfo = (FWL_DATEINFO*)m_arrDates.GetAt(i); + if (pDateInfo->rect.Contains(x, y)) { + return ++i; + } + } + return -1; +} +FX_BOOL CFWL_MonthCalendarImp::GetDayRect(int32_t iDay, CFX_RectF& rtDay) { + if (iDay <= 0 || iDay > m_arrDates.GetSize()) { + return FALSE; + } + FWL_DATEINFO* pDateInfo = (FWL_DATEINFO*)m_arrDates[iDay - 1]; + if (!pDateInfo) + return FALSE; + rtDay = pDateInfo->rect; + return TRUE; +} +CFWL_MonthCalendarImpDelegate::CFWL_MonthCalendarImpDelegate( + CFWL_MonthCalendarImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_MonthCalendarImpDelegate::OnProcessMessage( + CFWL_Message* pMessage) { + if (!pMessage) + return 0; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + int32_t iRet = 1; + switch (dwMsgCode) { + case FWL_MSGHASH_SetFocus: + case FWL_MSGHASH_KillFocus: { + OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus); + break; + } + case FWL_MSGHASH_Key: { + break; + } + case FWL_MSGHASH_Mouse: { + CFWL_MsgMouse* pMouse = static_cast<CFWL_MsgMouse*>(pMessage); + FX_DWORD dwCmd = pMouse->m_dwCmd; + switch (dwCmd) { + case FWL_MSGMOUSECMD_LButtonDown: { + OnLButtonDown(pMouse); + break; + } + case FWL_MSGMOUSECMD_LButtonUp: { + OnLButtonUp(pMouse); + break; + } + case FWL_MSGMOUSECMD_MouseMove: { + OnMouseMove(pMouse); + break; + } + case FWL_MSGMOUSECMD_MouseLeave: { + OnMouseLeave(pMouse); + break; + } + default: { break; } + } + break; + } + default: { + iRet = 0; + break; + } + } + CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); + return iRet; +} +FWL_ERR CFWL_MonthCalendarImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} + +void CFWL_MonthCalendarImpDelegate::OnActivate(CFWL_Message* pMsg) {} + +void CFWL_MonthCalendarImpDelegate::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_MonthCalendarImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iLBtnPartStates = FWL_PARTSTATE_MCD_Pressed; + m_pOwner->PrevMonth(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } else if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iRBtnPartStates |= FWL_PARTSTATE_MCD_Pressed; + m_pOwner->NextMonth(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } else if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) { + if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoToday) == + 0) { + m_pOwner->JumpToToday(); + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } + } else { + if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_MultiSelect) { + } else { + int32_t iOldSel = 0; + if (m_pOwner->m_arrSelDays.GetSize() > 0) { + iOldSel = m_pOwner->m_arrSelDays[0]; + } else { + return; + } + int32_t iCurSel = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy); + FX_BOOL bSelChanged = iCurSel > 0 && iCurSel != iOldSel; + if (bSelChanged) { + FWL_DATEINFO* lpDatesInfo = + (FWL_DATEINFO*)m_pOwner->m_arrDates.GetAt(iCurSel - 1); + CFX_RectF rtInvalidate(lpDatesInfo->rect); + if (iOldSel > 0) { + lpDatesInfo = (FWL_DATEINFO*)m_pOwner->m_arrDates.GetAt(iOldSel - 1); + rtInvalidate.Union(lpDatesInfo->rect); + } + m_pOwner->AddSelDay(iCurSel); + CFWL_EvtClick wmClick; + wmClick.m_pSrcTarget = m_pOwner->m_pInterface; + m_pOwner->DispatchEvent(&wmClick); + CFWL_EventMcdDateChanged wmDateSelected; + wmDateSelected.m_iStartDay = iCurSel; + wmDateSelected.m_iEndDay = iCurSel; + wmDateSelected.m_iOldMonth = m_pOwner->m_iCurMonth; + wmDateSelected.m_iOldYear = m_pOwner->m_iCurYear; + wmDateSelected.m_pSrcTarget = m_pOwner->m_pInterface; + m_pOwner->DispatchEvent(&wmDateSelected); + m_pOwner->Repaint(&rtInvalidate); + } + } + } +} +void CFWL_MonthCalendarImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iLBtnPartStates = 0; + m_pOwner->Repaint(&m_pOwner->m_rtLBtn); + } else if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_iRBtnPartStates = 0; + m_pOwner->Repaint(&m_pOwner->m_rtRBtn); + } else if (m_pOwner->m_rtDates.Contains(pMsg->m_fx, pMsg->m_fy)) { + int32_t iDay = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy); + if (iDay != -1) { + m_pOwner->AddSelDay(iDay); + } + } +} +void CFWL_MonthCalendarImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_MultiSelect) { + return; + } + FX_BOOL bRepaint = FALSE; + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, 0, 0); + if (m_pOwner->m_rtDates.Contains(pMsg->m_fx, pMsg->m_fy)) { + int32_t iHover = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy); + bRepaint = m_pOwner->m_iHovered != iHover; + if (bRepaint) { + if (m_pOwner->m_iHovered > 0) { + m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate); + } + if (iHover > 0) { + CFX_RectF rtDay; + m_pOwner->GetDayRect(iHover, rtDay); + if (rtInvalidate.IsEmpty()) { + rtInvalidate = rtDay; + } else { + rtInvalidate.Union(rtDay); + } + } + } + m_pOwner->m_iHovered = iHover; + } else { + bRepaint = m_pOwner->m_iHovered > 0; + if (bRepaint) { + m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate); + } + m_pOwner->m_iHovered = -1; + } + if (bRepaint && !rtInvalidate.IsEmpty()) { + m_pOwner->Repaint(&rtInvalidate); + } +} +void CFWL_MonthCalendarImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { + if (m_pOwner->m_iHovered > 0) { + CFX_RectF rtInvalidate; + rtInvalidate.Set(0, 0, 0, 0); + m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate); + m_pOwner->m_iHovered = -1; + if (!rtInvalidate.IsEmpty()) { + m_pOwner->Repaint(&rtInvalidate); + } + } +} diff --git a/xfa/src/fwl/basewidget/fwl_monthcalendarimp.h b/xfa/src/fwl/basewidget/fwl_monthcalendarimp.h new file mode 100644 index 0000000000..98b295ed6e --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_monthcalendarimp.h @@ -0,0 +1,243 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_MONTHCALENDARIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_MONTHCALENDARIMP_H_ + +#include "xfa/src/fgas/include/fx_datetime.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_MonthCalendarImpDelegate; + +extern uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth); + +class CFWL_MonthCalendarImp : public CFWL_WidgetImp { + public: + CFWL_MonthCalendarImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_MonthCalendarImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual int32_t CountSelect(); + virtual FX_BOOL GetSelect(int32_t& iYear, + int32_t& iMonth, + int32_t& iDay, + int32_t nIndex = 0); + virtual FX_BOOL SetSelect(int32_t iYear, int32_t iMonth, int32_t iDay); + + protected: + struct DATE { + DATE() : iYear(0), iMonth(0), iDay(0) {} + DATE(int32_t year, int32_t month, int32_t day) + : iYear(year), iMonth(month), iDay(day) {} + FX_BOOL operator<(const DATE& right) { + if (iYear < right.iYear) { + return TRUE; + } else if (iYear == right.iYear) { + if (iMonth < right.iMonth) { + return TRUE; + } else if (iMonth == right.iMonth) { + return iDay < right.iDay; + } + } + return FALSE; + } + FX_BOOL operator>(const DATE& right) { + if (iYear > right.iYear) { + return TRUE; + } else if (iYear == right.iYear) { + if (iMonth > right.iMonth) { + return TRUE; + } else if (iMonth == right.iMonth) { + return iDay > right.iDay; + } + } + return FALSE; + } + int32_t iYear; + int32_t iMonth; + int32_t iDay; + }; + + void DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawHeadBK(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawLButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawRButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawCaption(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawSeperator(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawDatesInBK(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawWeek(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawWeekNumber(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawWeekNumberSep(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawToday(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawDatesIn(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawDatesOut(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawDatesInCircle(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawTodayCircle(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + CFX_SizeF CalcSize(FX_BOOL bAutoSize = FALSE); + void LayOut(); + void CalcHeadSize(); + void CalcTodaySize(); + void CalDateItem(); + void GetCapValue(); + int32_t CalWeekNumber(int32_t iYear, int32_t iMonth, int32_t iDay); + FX_BOOL GetMinDate(int32_t& iYear, int32_t& iMonth, int32_t& iDay); + FX_BOOL SetMinDate(int32_t iYear, int32_t iMonth, int32_t iDay); + FX_BOOL GetMaxDate(int32_t& iYear, int32_t& iMonth, int32_t& iDay); + FX_BOOL SetMaxDate(int32_t iYear, int32_t iMonth, int32_t iDay); + FX_BOOL InitDate(); + void ClearDateItem(); + void ReSetDateItem(); + FX_BOOL NextMonth(); + FX_BOOL PrevMonth(); + void ChangeToMonth(int32_t iYear, int32_t iMonth); + FX_BOOL RemoveSelDay(int32_t iDay, FX_BOOL bAll = FALSE); + FX_BOOL AddSelDay(int32_t iDay); + FX_BOOL JumpToToday(); + void GetHeadText(int32_t iYear, int32_t iMonth, CFX_WideString& wsHead); + void GetTodayText(int32_t iYear, + int32_t iMonth, + int32_t iDay, + CFX_WideString& wsToday); + int32_t GetDayAtPoint(FX_FLOAT x, FX_FLOAT y); + FX_BOOL GetDayRect(int32_t iDay, CFX_RectF& rtDay); + + FX_BOOL m_bInit; + CFX_RectF m_rtHead; + CFX_RectF m_rtWeek; + CFX_RectF m_rtLBtn; + CFX_RectF m_rtRBtn; + CFX_RectF m_rtDates; + CFX_RectF m_rtHSep; + CFX_RectF m_rtHeadText; + CFX_RectF m_rtToday; + CFX_RectF m_rtTodayFlag; + CFX_RectF m_rtWeekNum; + CFX_RectF m_rtWeekNumSep; + CFX_RectF m_rtTemp; + CFX_WideString m_wsHead; + CFX_WideString m_wsToday; + CFX_DateTime* m_pDateTime; + CFX_PtrArray m_arrDates; + int32_t m_iCurYear; + int32_t m_iCurMonth; + int32_t m_iYear; + int32_t m_iMonth; + int32_t m_iDay; + int32_t m_iHovered; + int32_t m_iLBtnPartStates; + int32_t m_iRBtnPartStates; + DATE m_dtMin; + DATE m_dtMax; + CFX_SizeF m_szHead; + CFX_SizeF m_szCell; + CFX_SizeF m_szToday; + CFX_ArrayTemplate<int32_t> m_arrSelDays; + int32_t m_iMaxSel; + CFX_RectF m_rtClient; + FX_FLOAT m_fHeadWid; + FX_FLOAT m_fHeadHei; + FX_FLOAT m_fHeadBtnWid; + FX_FLOAT m_fHeadBtnHei; + FX_FLOAT m_fHeadBtnHMargin; + FX_FLOAT m_fHeadBtnVMargin; + FX_FLOAT m_fHeadTextWid; + FX_FLOAT m_fHeadTextHei; + FX_FLOAT m_fHeadTextHMargin; + FX_FLOAT m_fHeadTextVMargin; + FX_FLOAT m_fHSepWid; + FX_FLOAT m_fHSepHei; + FX_FLOAT m_fWeekNumWid; + FX_FLOAT m_fSepDOffset; + FX_FLOAT m_fSepX; + FX_FLOAT m_fSepY; + FX_FLOAT m_fWeekNumHeigh; + FX_FLOAT m_fWeekWid; + FX_FLOAT m_fWeekHei; + FX_FLOAT m_fDateCellWid; + FX_FLOAT m_fDateCellHei; + FX_FLOAT m_fTodayWid; + FX_FLOAT m_fTodayHei; + FX_FLOAT m_fTodayFlagWid; + FX_FLOAT m_fMCWid; + FX_FLOAT m_fMCHei; + friend class CFWL_MonthCalendarImpDelegate; +}; + +struct FWL_DATEINFO { + FWL_DATEINFO(int32_t day, + int32_t dayofweek, + FX_DWORD dwSt, + CFX_RectF rc, + CFX_WideString& wsday) + : iDay(day), + iDayOfWeek(dayofweek), + dwStates(dwSt), + rect(rc), + wsDay(wsday) {} + int32_t iDay; + int32_t iDayOfWeek; + FX_DWORD dwStates; + CFX_RectF rect; + CFX_WideString wsDay; +}; + +class CFWL_MonthCalendarImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_MonthCalendarImpDelegate(CFWL_MonthCalendarImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnActivate(CFWL_Message* pMsg); + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + CFWL_MonthCalendarImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_MONTHCALENDARIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_pictureboximp.cpp b/xfa/src/fwl/basewidget/fwl_pictureboximp.cpp new file mode 100644 index 0000000000..d0efaf3d2a --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_pictureboximp.cpp @@ -0,0 +1,151 @@ +// 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/src/fwl/basewidget/fwl_pictureboximp.h" + +#include "xfa/include/fwl/lightwidget/picturebox.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +// static +IFWL_PictureBox* IFWL_PictureBox::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_PictureBox* pPictureBox = new IFWL_PictureBox; + CFWL_PictureBoxImp* pPictureBoxImpl = + new CFWL_PictureBoxImp(properties, pOuter); + pPictureBox->SetImpl(pPictureBoxImpl); + pPictureBoxImpl->SetInterface(pPictureBox); + return pPictureBox; +} +IFWL_PictureBox::IFWL_PictureBox() {} + +CFWL_PictureBoxImp::CFWL_PictureBoxImp( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_bTop(FALSE), + m_bVCenter(FALSE), + m_bButton(FALSE) { + m_rtClient.Reset(); + m_rtImage.Reset(); + m_matrix.SetIdentity(); +} +CFWL_PictureBoxImp::~CFWL_PictureBoxImp() {} +FWL_ERR CFWL_PictureBoxImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_PictureBox; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_PictureBoxImp::GetClassID() const { + return FWL_CLASSHASH_PictureBox; +} +FWL_ERR CFWL_PictureBoxImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_PictureBoxImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PictureBoxImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_PictureBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + if (!m_pProperties->m_pDataProvider) + return FWL_ERR_Indefinite; + CFX_DIBitmap* pBitmap = + static_cast<IFWL_PictureBoxDP*>(m_pProperties->m_pDataProvider) + ->GetPicture(m_pInterface); + if (pBitmap) { + rect.Set(0, 0, (FX_FLOAT)pBitmap->GetWidth(), + (FX_FLOAT)pBitmap->GetHeight()); + } + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PictureBoxImp::Update() { + if (IsLocked()) { + return FWL_ERR_Succeeded; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + GetClientRect(m_rtClient); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PictureBoxImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = GetAvailableTheme(); + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_PTB_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_PTB_Edge, pTheme, pMatrix); + } + DrawBkground(pGraphics, pTheme, pMatrix); + return FWL_ERR_Succeeded; +} +void CFWL_PictureBoxImp::DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + IFWL_PictureBoxDP* pPictureDP = + static_cast<IFWL_PictureBoxDP*>(m_pProperties->m_pDataProvider); + if (!pPictureDP) + return; + + CFX_DIBitmap* pPicture = pPictureDP->GetPicture(m_pInterface); + CFX_Matrix matrix; + pPictureDP->GetMatrix(m_pInterface, matrix); + if (!pPicture) + return; + + matrix.Concat(*pMatrix); + FX_FLOAT fx = (FX_FLOAT)pPicture->GetWidth(); + FX_FLOAT fy = (FX_FLOAT)pPicture->GetHeight(); + if (fx > m_rtClient.width) { + fx = m_rtClient.width; + } + if (fy > m_rtClient.height) { + fy = m_rtClient.height; + } + pGraphics->DrawImage(pPicture, CFX_PointF((m_rtClient.width - fx) / 2, + (m_rtClient.height - fy) / 2), + &matrix); +} +FX_BOOL CFWL_PictureBoxImp::VStyle(FX_BOOL dwStyle) { + switch (dwStyle & FWL_STYLEEXT_PTB_VAlignMask) { + case FWL_STYLEEXT_PTB_Top: { + return m_bTop = TRUE; + break; + } + case FWL_STYLEEXT_PTB_Vcenter: { + return m_bVCenter = TRUE; + break; + } + case FWL_STYLEEXT_PTB_Bottom: { + return m_bButton = TRUE; + break; + } + } + return FALSE; +} +CFWL_PictureBoxImpDelegate::CFWL_PictureBoxImpDelegate( + CFWL_PictureBoxImp* pOwner) + : m_pOwner(pOwner) {} +FWL_ERR CFWL_PictureBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} diff --git a/xfa/src/fwl/basewidget/fwl_pictureboximp.h b/xfa/src/fwl/basewidget/fwl_pictureboximp.h new file mode 100644 index 0000000000..cfa50afb70 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_pictureboximp.h @@ -0,0 +1,53 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_PICTUREBOXIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_PICTUREBOXIMP_H_ + +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_PictureBoxImpDelegate; + +class CFWL_PictureBoxImp : public CFWL_WidgetImp { + public: + CFWL_PictureBoxImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_PictureBoxImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + + protected: + void DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix = NULL); + FX_BOOL VStyle(FX_BOOL dwStyle); + CFX_RectF m_rtClient; + CFX_RectF m_rtImage; + CFX_Matrix m_matrix; + FX_BOOL m_bTop; + FX_BOOL m_bVCenter; + FX_BOOL m_bButton; + friend class CFWL_PictureBoxImpDelegate; +}; +class CFWL_PictureBoxImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_PictureBoxImpDelegate(CFWL_PictureBoxImp* pOwner); + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + CFWL_PictureBoxImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_PICTUREBOXIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_pushbuttonimp.cpp b/xfa/src/fwl/basewidget/fwl_pushbuttonimp.cpp new file mode 100644 index 0000000000..2325217dc2 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_pushbuttonimp.cpp @@ -0,0 +1,550 @@ +// 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/src/fwl/basewidget/fwl_pushbuttonimp.h" + +#include "xfa/include/fwl/basewidget/fwl_pushbutton.h" +#include "xfa/src/fdp/include/fde_tto.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +// static +IFWL_PushButton* IFWL_PushButton::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_PushButton* pPushButton = new IFWL_PushButton; + CFWL_PushButtonImp* pPushButtonImpl = + new CFWL_PushButtonImp(properties, pOuter); + pPushButton->SetImpl(pPushButtonImpl); + pPushButtonImpl->SetInterface(pPushButton); + return pPushButton; +} +IFWL_PushButton::IFWL_PushButton() {} + +CFWL_PushButtonImp::CFWL_PushButtonImp( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_bBtnDown(FALSE), + m_dwTTOStyles(FDE_TTOSTYLE_SingleLine), + m_iTTOAlign(FDE_TTOALIGNMENT_Center) { + m_rtClient.Set(0, 0, 0, 0); + m_rtCaption.Set(0, 0, 0, 0); +} +CFWL_PushButtonImp::~CFWL_PushButtonImp() {} +FWL_ERR CFWL_PushButtonImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_PushButton; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_PushButtonImp::GetClassID() const { + return FWL_CLASSHASH_PushButton; +} +FWL_ERR CFWL_PushButtonImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_PushButtonImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PushButtonImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_PushButtonImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + if (m_pProperties->m_pThemeProvider == NULL) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + CFX_WideString wsCaption; + IFWL_PushButtonDP* pData = + static_cast<IFWL_PushButtonDP*>(m_pProperties->m_pDataProvider); + if (pData) { + pData->GetCaption(m_pInterface, wsCaption); + } + int32_t iLen = wsCaption.GetLength(); + if (iLen > 0) { + CFX_SizeF sz = CalcTextSize(wsCaption, m_pProperties->m_pThemeProvider); + rect.Set(0, 0, sz.x, sz.y); + } + FX_FLOAT* fcaption = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_PSB_Margin)); + rect.Inflate(*fcaption, *fcaption); + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PushButtonImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) { + if ((dwStates & FWL_WGTSTATE_Disabled) && bSet) { + m_pProperties->m_dwStates = FWL_WGTSTATE_Disabled; + return FWL_ERR_Succeeded; + } + return CFWL_WidgetImp::SetStates(dwStates, bSet); +} +FWL_ERR CFWL_PushButtonImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + UpdateTextOutStyles(); + GetClientRect(m_rtClient); + m_rtCaption = m_rtClient; + FX_FLOAT* fcaption = + static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_PSB_Margin)); + m_rtCaption.Inflate(-*fcaption, -*fcaption); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PushButtonImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_PushButtonDP* pData = + static_cast<IFWL_PushButtonDP*>(m_pProperties->m_pDataProvider); + CFX_DIBitmap* pPicture = NULL; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_PSB_Border, m_pProperties->m_pThemeProvider, + pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_PSB_Edge, m_pProperties->m_pThemeProvider, + pMatrix); + } + DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix); + CFX_Matrix matrix; + matrix.Concat(*pMatrix); + FX_FLOAT iPicwidth = 0; + FX_FLOAT ipicheight = 0; + CFX_WideString wsCaption; + if (pData) { + pData->GetCaption(m_pInterface, wsCaption); + } + CFX_RectF rtText; + rtText.Set(0, 0, 0, 0); + if (!wsCaption.IsEmpty()) { + CalcTextRect(wsCaption, pTheme, 0, m_iTTOAlign, rtText); + } + switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_PSB_ModeMask) { + case FWL_STYLEEXT_PSB_TextOnly: + DrawText(pGraphics, m_pProperties->m_pThemeProvider, &matrix); + break; + case FWL_STYLEEXT_PSB_IconOnly: + if (pData) { + pPicture = pData->GetPicture(m_pInterface); + } + if (pPicture) { + CFX_PointF point; + switch (m_iTTOAlign) { + case 0: { + point.x = m_rtClient.left; + point.y = m_rtClient.top; + break; + } + case 1: { + point.x = m_rtClient.left + + (m_rtClient.width / 2 - pPicture->GetWidth() / 2); + point.y = m_rtClient.top; + break; + } + case 2: + point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth(); + point.y = m_rtClient.top; + break; + case 4: + point.x = m_rtClient.left; + point.y = m_rtClient.top + m_rtClient.height / 2 - + pPicture->GetHeight() / 2; + break; + case 5: + point.x = m_rtClient.left + + (m_rtClient.width / 2 - pPicture->GetWidth() / 2); + point.y = m_rtClient.top + m_rtClient.height / 2 - + pPicture->GetHeight() / 2; + break; + case 6: + point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth(); + point.y = m_rtClient.top + m_rtClient.height / 2 - + pPicture->GetHeight() / 2; + break; + case 8: + point.x = m_rtClient.left; + point.y = + m_rtClient.top + m_rtClient.height - pPicture->GetHeight(); + break; + case 9: + point.x = m_rtClient.left + + (m_rtClient.width / 2 - pPicture->GetWidth() / 2); + point.y = + m_rtClient.top + m_rtClient.height - pPicture->GetHeight(); + break; + case 10: + point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth(); + point.y = + m_rtClient.top + m_rtClient.height - pPicture->GetHeight(); + break; + } + pGraphics->DrawImage(pPicture, point, &matrix); + } + break; + case FWL_STYLEEXT_PSB_TextIcon: + if (pPicture) { + CFX_PointF point; + switch (m_iTTOAlign) { + case 0: { + point.x = m_rtClient.left; + point.y = m_rtClient.top; + iPicwidth = (FX_FLOAT)(pPicture->GetWidth() - 7); + ipicheight = + pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2; + break; + } + case 1: { + point.x = + m_rtClient.left + (m_rtClient.width / 2 - + (pPicture->GetWidth() + rtText.width) / 2); + point.y = m_rtClient.top; + iPicwidth = pPicture->GetWidth() - + ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) + + rtText.width / 2 - 7; + ipicheight = + pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2; + break; + } + case 2: + point.x = m_rtClient.left + m_rtClient.width - + pPicture->GetWidth() - rtText.width; + point.y = m_rtClient.top; + iPicwidth = m_rtClient.left + m_rtClient.width - point.x - + pPicture->GetWidth() - rtText.width + 7; + ipicheight = + pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2; + break; + case 4: + point.x = m_rtClient.left; + point.y = m_rtClient.top + m_rtClient.height / 2 - + pPicture->GetHeight() / 2; + iPicwidth = m_rtClient.left + pPicture->GetWidth() - 7; + break; + case 5: + point.x = + m_rtClient.left + (m_rtClient.width / 2 - + (pPicture->GetWidth() + rtText.width) / 2); + point.y = m_rtClient.top + m_rtClient.height / 2 - + pPicture->GetHeight() / 2; + iPicwidth = pPicture->GetWidth() - + ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) + + rtText.width / 2 - 7; + break; + case 6: + point.x = m_rtClient.left + m_rtClient.width - + pPicture->GetWidth() - rtText.width; + point.y = m_rtClient.top + m_rtClient.height / 2 - + pPicture->GetHeight() / 2; + iPicwidth = m_rtClient.left + m_rtClient.width - point.x - + pPicture->GetWidth() - rtText.width + 7; + break; + case 8: + point.x = m_rtClient.left; + point.y = + m_rtClient.top + m_rtClient.height - pPicture->GetHeight(); + iPicwidth = (FX_FLOAT)(pPicture->GetWidth() - 7); + ipicheight -= rtText.height / 2; + break; + case 9: + point.x = + m_rtClient.left + (m_rtClient.width / 2 - + (pPicture->GetWidth() + rtText.width) / 2); + point.y = + m_rtClient.top + m_rtClient.height - pPicture->GetHeight(); + iPicwidth = pPicture->GetWidth() - + ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) + + rtText.width / 2 - 7; + ipicheight -= rtText.height / 2; + break; + case 10: + point.x = m_rtClient.left + m_rtClient.width - + pPicture->GetWidth() - rtText.width; + point.y = + m_rtClient.top + m_rtClient.height - pPicture->GetHeight(); + iPicwidth = m_rtClient.left + m_rtClient.width - point.x - + pPicture->GetWidth() - rtText.width + 7; + ipicheight -= rtText.height / 2; + break; + } + pGraphics->DrawImage(pPicture, point, &matrix); + } + matrix.e += m_rtClient.left + iPicwidth; + matrix.f += m_rtClient.top + ipicheight; + DrawText(pGraphics, m_pProperties->m_pThemeProvider, &matrix); + break; + } + return FWL_ERR_Succeeded; +} +void CFWL_PushButtonImp::DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_PSB_Background; + param.m_dwStates = GetPartStates(); + param.m_pGraphics = pGraphics; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = m_rtClient; + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + param.m_pData = &m_rtCaption; + } + pTheme->DrawBackground(¶m); +} +void CFWL_PushButtonImp::DrawText(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (!m_pProperties->m_pDataProvider) + return; + CFX_WideString wsCaption; + m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption); + if (wsCaption.IsEmpty()) { + return; + } + CFWL_ThemeText param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_PSB_Caption; + param.m_dwStates = GetPartStates(); + param.m_pGraphics = pGraphics; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = m_rtCaption; + param.m_wsText = wsCaption; + param.m_dwTTOStyles = m_dwTTOStyles; + param.m_iTTOAlign = m_iTTOAlign; + pTheme->DrawText(¶m); +} +FX_DWORD CFWL_PushButtonImp::GetPartStates() { + FX_DWORD dwStates = FWL_PARTSTATE_PSB_Normal; + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + dwStates |= FWL_PARTSTATE_PSB_Focused; + } + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { + dwStates = FWL_PARTSTATE_PSB_Disabled; + } else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) { + dwStates |= FWL_PARTSTATE_PSB_Pressed; + } else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) { + dwStates |= FWL_PARTSTATE_PSB_Hovered; + } else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Default) { + dwStates |= FWL_PARTSTATE_PSB_Default; + } + return dwStates; +} +void CFWL_PushButtonImp::UpdateTextOutStyles() { + m_iTTOAlign = FDE_TTOALIGNMENT_Center; + switch (m_pProperties->m_dwStyleExes & + (FWL_STYLEEXT_PSB_HLayoutMask | FWL_STYLEEXT_PSB_VLayoutMask)) { + case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Top: { + m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft; + break; + } + case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Top: { + m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter; + break; + } + case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Top: { + m_iTTOAlign = FDE_TTOALIGNMENT_TopRight; + break; + } + case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_VCenter: { + m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; + break; + } + case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_VCenter: { + m_iTTOAlign = FDE_TTOALIGNMENT_Center; + break; + } + case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_VCenter: { + m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight; + break; + } + case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Bottom: { + m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft; + break; + } + case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Bottom: { + m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter; + break; + } + case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Bottom: { + m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight; + break; + } + default: {} + } + m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) { + m_dwTTOStyles |= FDE_TTOSTYLE_RTL; + } +} +CFWL_PushButtonImpDelegate::CFWL_PushButtonImpDelegate( + CFWL_PushButtonImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_PushButtonImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + if (!m_pOwner->IsEnabled()) { + return 1; + } + 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_PushButtonImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_PushButtonImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_PushButtonImpDelegate::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_PushButtonImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { + if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { + m_pOwner->SetFocus(TRUE); + } + m_pOwner->m_bBtnDown = TRUE; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed; + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_PushButtonImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { + m_pOwner->m_bBtnDown = FALSE; + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed; + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered; + } else { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed; + } + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + CFWL_EvtClick wmClick; + wmClick.m_pSrcTarget = m_pOwner->m_pInterface; + m_pOwner->DispatchEvent(&wmClick); + } + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_PushButtonImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { + FX_BOOL bRepaint = FALSE; + if (m_pOwner->m_bBtnDown) { + if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) == 0) { + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed; + bRepaint = TRUE; + } + if (m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered; + bRepaint = TRUE; + } + } else { + if (m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) { + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed; + bRepaint = TRUE; + } + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) { + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered; + bRepaint = TRUE; + } + } + } else { + if (!m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { + return; + } + if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) { + m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered; + bRepaint = TRUE; + } + } + if (bRepaint) { + m_pOwner->Repaint(&m_pOwner->m_rtClient); + } +} +void CFWL_PushButtonImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { + m_pOwner->m_bBtnDown = FALSE; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered; + m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed; + m_pOwner->Repaint(&m_pOwner->m_rtClient); +} +void CFWL_PushButtonImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) { + if (pMsg->m_dwKeyCode == FWL_VKEY_Return) { + CFWL_EvtMouse wmMouse; + wmMouse.m_pSrcTarget = m_pOwner->m_pInterface; + wmMouse.m_dwCmd = FWL_MSGMOUSECMD_LButtonUp; + m_pOwner->DispatchEvent(&wmMouse); + CFWL_EvtClick wmClick; + wmClick.m_pSrcTarget = m_pOwner->m_pInterface; + m_pOwner->DispatchEvent(&wmClick); + return; + } + if (pMsg->m_dwKeyCode != FWL_VKEY_Tab) { + return; + } + m_pOwner->DispatchKeyEvent(pMsg); +} diff --git a/xfa/src/fwl/basewidget/fwl_pushbuttonimp.h b/xfa/src/fwl/basewidget/fwl_pushbuttonimp.h new file mode 100644 index 0000000000..5869074ba7 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_pushbuttonimp.h @@ -0,0 +1,65 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_PUSHBUTTONIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_PUSHBUTTONIMP_H_ + +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_PushButtonImpDelegate; + +class CFWL_PushButtonImp : public CFWL_WidgetImp { + public: + CFWL_PushButtonImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual ~CFWL_PushButtonImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR SetStates(FX_DWORD dwStates, FX_BOOL bSet = TRUE); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + + protected: + void DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawText(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + FX_DWORD GetPartStates(); + void UpdateTextOutStyles(); + CFX_RectF m_rtClient; + CFX_RectF m_rtCaption; + FX_BOOL m_bBtnDown; + FX_DWORD m_dwTTOStyles; + int32_t m_iTTOAlign; + friend class CFWL_PushButtonImpDelegate; +}; +class CFWL_PushButtonImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_PushButtonImpDelegate(CFWL_PushButtonImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + void OnKeyDown(CFWL_MsgKey* pMsg); + CFWL_PushButtonImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_PUSHBUTTONIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_scrollbarimp.cpp b/xfa/src/fwl/basewidget/fwl_scrollbarimp.cpp new file mode 100644 index 0000000000..c43ebbbc85 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_scrollbarimp.cpp @@ -0,0 +1,805 @@ +// 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/src/fwl/basewidget/fwl_scrollbarimp.h" + +#include "xfa/include/fwl/basewidget/fwl_scrollbar.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +#define FWL_SCROLLBAR_Elapse 500 +#define FWL_SCROLLBAR_MinThumb 5 + +// static +IFWL_ScrollBar* IFWL_ScrollBar::Create( + const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_ScrollBar* pScrollBar = new IFWL_ScrollBar; + CFWL_ScrollBarImp* pScrollBarImpl = new CFWL_ScrollBarImp(properties, pOuter); + pScrollBar->SetImpl(pScrollBarImpl); + pScrollBarImpl->SetInterface(pScrollBar); + return pScrollBar; +} +IFWL_ScrollBar::IFWL_ScrollBar() {} +FX_BOOL IFWL_ScrollBar::IsVertical() { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->IsVertical(); +} +FWL_ERR IFWL_ScrollBar::GetRange(FX_FLOAT& fMin, FX_FLOAT& fMax) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->GetRange(fMin, fMax); +} +FWL_ERR IFWL_ScrollBar::SetRange(FX_FLOAT fMin, FX_FLOAT fMax) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->SetRange(fMin, fMax); +} +FX_FLOAT IFWL_ScrollBar::GetPageSize() { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->GetPageSize(); +} +FWL_ERR IFWL_ScrollBar::SetPageSize(FX_FLOAT fPageSize) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->SetPageSize(fPageSize); +} +FX_FLOAT IFWL_ScrollBar::GetStepSize() { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->GetStepSize(); +} +FWL_ERR IFWL_ScrollBar::SetStepSize(FX_FLOAT fStepSize) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->SetStepSize(fStepSize); +} +FX_FLOAT IFWL_ScrollBar::GetPos() { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->GetPos(); +} +FWL_ERR IFWL_ScrollBar::SetPos(FX_FLOAT fPos) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->SetPos(fPos); +} +FX_FLOAT IFWL_ScrollBar::GetTrackPos() { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->GetTrackPos(); +} +FWL_ERR IFWL_ScrollBar::SetTrackPos(FX_FLOAT fTrackPos) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->SetTrackPos(fTrackPos); +} +FX_BOOL IFWL_ScrollBar::DoScroll(FX_DWORD dwCode, FX_FLOAT fPos) { + return static_cast<CFWL_ScrollBarImp*>(GetImpl())->DoScroll(dwCode, fPos); +} +CFWL_ScrollBarImp::CFWL_ScrollBarImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_WidgetImp(properties, pOuter), + m_hTimer(nullptr), + m_fRangeMin(0), + m_fRangeMax(-1), + m_fPageSize(0), + m_fStepSize(0), + m_fPos(0), + m_fTrackPos(0), + m_iMinButtonState(FWL_PARTSTATE_SCB_Normal), + m_iMaxButtonState(FWL_PARTSTATE_SCB_Normal), + m_iThumbButtonState(FWL_PARTSTATE_SCB_Normal), + m_iMinTrackState(FWL_PARTSTATE_SCB_Normal), + m_iMaxTrackState(FWL_PARTSTATE_SCB_Normal), + m_fLastTrackPos(0), + m_cpTrackPointX(0), + m_cpTrackPointY(0), + m_iMouseWheel(0), + m_bTrackMouseLeave(FALSE), + m_bMouseHover(FALSE), + m_bMouseDown(FALSE), + m_bRepaintThumb(FALSE), + m_fButtonLen(0), + m_bMinSize(FALSE), + m_bCustomLayout(FALSE), + m_fMinThumb(FWL_SCROLLBAR_MinThumb) { + m_rtClient.Reset(); + m_rtThumb.Reset(); + m_rtMinBtn.Reset(); + m_rtMaxBtn.Reset(); + m_rtMinTrack.Reset(); + m_rtMaxTrack.Reset(); +} +CFWL_ScrollBarImp::~CFWL_ScrollBarImp() {} +FWL_ERR CFWL_ScrollBarImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_ScrollBar; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ScrollBarImp::GetClassID() const { + return FWL_CLASSHASH_ScrollBar; +} +FWL_ERR CFWL_ScrollBarImp::Initialize() { + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_ScrollBarImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ScrollBarImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_ScrollBarImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + FX_FLOAT* pfMinWidth = static_cast<FX_FLOAT*>( + GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); + if (!pfMinWidth) + return FWL_ERR_Indefinite; + if (IsVertical()) { + rect.Set(0, 0, (*pfMinWidth), (*pfMinWidth) * 3); + } else { + rect.Set(0, 0, (*pfMinWidth) * 3, (*pfMinWidth)); + } + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ScrollBarImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + Layout(); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ScrollBarImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (HasBorder()) { + DrawBorder(pGraphics, FWL_PART_SCB_Border, pTheme, pMatrix); + } + if (HasEdge()) { + DrawEdge(pGraphics, FWL_PART_SCB_Edge, pTheme, pMatrix); + } + DrawTrack(pGraphics, pTheme, TRUE, pMatrix); + DrawTrack(pGraphics, pTheme, FALSE, pMatrix); + DrawArrowBtn(pGraphics, pTheme, TRUE, pMatrix); + DrawArrowBtn(pGraphics, pTheme, FALSE, pMatrix); + DrawThumb(pGraphics, pTheme, pMatrix); + return FWL_ERR_Succeeded; +} +inline FX_BOOL CFWL_ScrollBarImp::IsVertical() { + return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_SCB_Vert; +} +FWL_ERR CFWL_ScrollBarImp::GetRange(FX_FLOAT& fMin, FX_FLOAT& fMax) { + fMin = m_fRangeMin; + fMax = m_fRangeMax; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ScrollBarImp::SetRange(FX_FLOAT fMin, FX_FLOAT fMax) { + m_fRangeMin = fMin; + m_fRangeMax = fMax; + return FWL_ERR_Succeeded; +} +FX_FLOAT CFWL_ScrollBarImp::GetPageSize() { + return m_fPageSize; +} +FWL_ERR CFWL_ScrollBarImp::SetPageSize(FX_FLOAT fPageSize) { + m_fPageSize = fPageSize; + return FWL_ERR_Succeeded; +} +FX_FLOAT CFWL_ScrollBarImp::GetStepSize() { + return m_fStepSize; +} +FWL_ERR CFWL_ScrollBarImp::SetStepSize(FX_FLOAT fStepSize) { + m_fStepSize = fStepSize; + return FWL_ERR_Succeeded; +} +FX_FLOAT CFWL_ScrollBarImp::GetPos() { + return m_fPos; +} +FWL_ERR CFWL_ScrollBarImp::SetPos(FX_FLOAT fPos) { + m_fPos = fPos; + return FWL_ERR_Succeeded; +} +FX_FLOAT CFWL_ScrollBarImp::GetTrackPos() { + return m_fTrackPos; +} +FWL_ERR CFWL_ScrollBarImp::SetTrackPos(FX_FLOAT fTrackPos) { + m_fTrackPos = fTrackPos; + CalcThumbButtonRect(m_rtThumb); + CalcMinTrackRect(m_rtMinTrack); + CalcMaxTrackRect(m_rtMaxTrack); + return FWL_ERR_Succeeded; +} +FX_BOOL CFWL_ScrollBarImp::DoScroll(FX_DWORD dwCode, FX_FLOAT fPos) { + switch (dwCode) { + case FWL_SCBCODE_Min: + case FWL_SCBCODE_Max: + case FWL_SCBCODE_PageBackward: + case FWL_SCBCODE_PageForward: + case FWL_SCBCODE_StepBackward: + break; + case FWL_SCBCODE_StepForward: + break; + case FWL_SCBCODE_Pos: + case FWL_SCBCODE_TrackPos: + case FWL_SCBCODE_EndScroll: + break; + default: { return FALSE; } + } + return OnScroll(dwCode, fPos); +} +int32_t CFWL_ScrollBarImp::Run(FWL_HTIMER hTimer) { + if (m_hTimer) { + FWL_StopTimer(m_hTimer); + } + if (!SendEvent()) { + m_hTimer = FWL_StartTimer(this, 0); + } + return 1; +} +FWL_ERR CFWL_ScrollBarImp::SetOuter(IFWL_Widget* pOuter) { + m_pOuter = pOuter; + return FWL_ERR_Succeeded; +} +void CFWL_ScrollBarImp::DrawTrack(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + FX_BOOL bLower, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = bLower ? FWL_PART_SCB_LowerTrack : FWL_PART_SCB_UpperTrack; + param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) + ? FWL_PARTSTATE_SCB_Disabled + : (bLower ? m_iMinTrackState : m_iMaxTrackState); + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = bLower ? m_rtMinTrack : m_rtMaxTrack; + pTheme->DrawBackground(¶m); +} +void CFWL_ScrollBarImp::DrawArrowBtn(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + FX_BOOL bMinBtn, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = bMinBtn ? FWL_PART_SCB_ForeArrow : FWL_PART_SCB_BackArrow; + param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) + ? FWL_PARTSTATE_SCB_Disabled + : (bMinBtn ? m_iMinButtonState : m_iMaxButtonState); + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = bMinBtn ? m_rtMinBtn : m_rtMaxBtn; + if (param.m_rtPart.height > 0 && param.m_rtPart.width > 0) { + pTheme->DrawBackground(¶m); + } +} +void CFWL_ScrollBarImp::DrawThumb(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (!IsEnabled()) { + } + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_SCB_Thumb; + param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) + ? FWL_PARTSTATE_SCB_Disabled + : m_iThumbButtonState; + param.m_pGraphics = pGraphics; + param.m_matrix.Concat(*pMatrix); + param.m_rtPart = m_rtThumb; + pTheme->DrawBackground(¶m); +} +void CFWL_ScrollBarImp::Layout() { + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + CFWL_ThemePart part; + part.m_pWidget = m_pInterface; + m_fMinThumb = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_CAPACITY_SCB_Size)); + m_bCustomLayout = pTheme->IsCustomizedLayout(m_pInterface); + GetClientRect(m_rtClient); + CalcButtonLen(); + CalcMinButtonRect(m_rtMinBtn); + CalcMaxButtonRect(m_rtMaxBtn); + CalcThumbButtonRect(m_rtThumb); + CalcMinTrackRect(m_rtMinTrack); + CalcMaxTrackRect(m_rtMaxTrack); +} +void CFWL_ScrollBarImp::CalcButtonLen() { + m_fButtonLen = IsVertical() ? m_rtClient.width : m_rtClient.height; + FX_FLOAT fLength = IsVertical() ? m_rtClient.height : m_rtClient.width; + if (fLength < m_fButtonLen * 2) { + m_fButtonLen = fLength / 2; + m_bMinSize = TRUE; + } else { + m_bMinSize = FALSE; + } +} +void CFWL_ScrollBarImp::CalcMinButtonRect(CFX_RectF& rect) { + if (m_bCustomLayout) { + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + CFWL_ThemePart pPart; + pPart.m_rtPart = m_rtMinBtn; + pPart.m_pWidget = m_pInterface; + pPart.m_iPart = FWL_PART_SCB_ForeArrow; + pPart.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) + ? FWL_PARTSTATE_SCB_Disabled + : m_iMinButtonState; + pTheme->GetPartRect(&pPart, rect); + } else { + rect.left = m_rtClient.left; + rect.top = m_rtClient.top; + rect.width = IsVertical() ? m_rtClient.width : m_fButtonLen; + rect.height = IsVertical() ? m_fButtonLen : m_rtClient.height; + } +} +void CFWL_ScrollBarImp::CalcMaxButtonRect(CFX_RectF& rect) { + if (m_bCustomLayout) { + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + CFWL_ThemePart pPart; + pPart.m_rtPart = m_rtMaxBtn; + pPart.m_pWidget = m_pInterface; + pPart.m_iPart = FWL_PART_SCB_BackArrow; + pPart.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) + ? FWL_PARTSTATE_SCB_Disabled + : m_iMaxButtonState; + pTheme->GetPartRect(&pPart, rect); + } else { + rect.left = + IsVertical() ? m_rtClient.left : m_rtClient.right() - m_fButtonLen; + rect.top = + IsVertical() ? m_rtClient.bottom() - m_fButtonLen : m_rtClient.top; + rect.width = IsVertical() ? m_rtClient.width : m_fButtonLen; + rect.height = IsVertical() ? m_fButtonLen : m_rtClient.height; + } +} +void CFWL_ScrollBarImp::CalcThumbButtonRect(CFX_RectF& rect) { + if (!IsEnabled()) { + m_rtThumb.Reset(); + return; + } + if (m_bMinSize) { + m_rtThumb.Empty(); + return; + } + FX_FLOAT fRange = m_fRangeMax - m_fRangeMin; + memset(&rect, 0, sizeof(CFX_Rect)); + if (fRange < 0) { + if (IsVertical()) { + rect.Set(m_rtClient.left, m_rtMaxBtn.bottom(), m_rtClient.width, 0); + } else { + rect.Set(m_rtMaxBtn.right(), m_rtClient.top, 0, m_rtClient.height); + } + return; + } + CFX_RectF rtClient = m_rtClient; + FX_FLOAT fLength = IsVertical() ? rtClient.height : rtClient.width; + FX_FLOAT fSize = m_fButtonLen; + if (m_bCustomLayout) { + if (IsVertical()) { + fLength = fLength - m_rtMinBtn.height - m_rtMaxBtn.height; + if (fLength < m_rtMinBtn.height || fLength < m_rtMaxBtn.height) { + fLength = 0.0f; + } + } else { + fLength = fLength - m_rtMinBtn.width - m_rtMaxBtn.width; + if (fLength < m_rtMinBtn.width || fLength < m_rtMaxBtn.width) { + fLength = 0.0f; + } + } + } else { + fLength -= fSize * 2.0f; + if (fLength < fSize) { + fLength = 0.0f; + } + } + FX_FLOAT fThumbSize = fLength * fLength / (fRange + fLength); + if (fThumbSize < m_fMinThumb) { + fThumbSize = m_fMinThumb; + } + FX_FLOAT fDiff = fLength - fThumbSize; + if (fDiff < 0.0f) { + fDiff = 0.0f; + } + FX_FLOAT fTrackPos = m_fTrackPos; + if (fTrackPos > m_fRangeMax) { + fTrackPos = m_fRangeMax; + } + if (fTrackPos < m_fRangeMin) { + fTrackPos = m_fRangeMin; + } + if (!fRange) + return; + if (m_bCustomLayout) { + FX_FLOAT iPos = fDiff * (fTrackPos - m_fRangeMin) / fRange; + rect.left = rtClient.left; + if (!IsVertical()) { + if ((m_rtMinBtn.right() == m_rtMaxBtn.left && m_rtMinBtn.width > 0 && + m_rtMaxBtn.width > 0) || + (0 == m_rtMinBtn.width && 0 == m_rtMaxBtn.width)) { + rect.left += iPos; + } else { + rect.left += m_rtMinBtn.right() + iPos; + } + } + rect.top = rtClient.top; + if (IsVertical()) { + if ((m_rtMinBtn.bottom() == m_rtMaxBtn.top && m_rtMinBtn.height > 0 && + m_rtMaxBtn.height > 0) || + (0 == m_rtMinBtn.height && 0 == m_rtMaxBtn.height)) { + rect.top += iPos; + } else { + rect.top += m_rtMinBtn.bottom() + iPos; + } + } + rect.width = IsVertical() ? rtClient.width : fThumbSize; + rect.height = IsVertical() ? fThumbSize : rtClient.height; + } else { + FX_FLOAT iPos = fSize + fDiff * (fTrackPos - m_fRangeMin) / fRange; + rect.left = rtClient.left; + if (!IsVertical()) { + rect.left += iPos; + } + rect.top = rtClient.top; + if (IsVertical()) { + rect.top += iPos; + } + rect.width = IsVertical() ? rtClient.width : fThumbSize; + rect.height = IsVertical() ? fThumbSize : rtClient.height; + } +} +void CFWL_ScrollBarImp::CalcMinTrackRect(CFX_RectF& rect) { + if (m_bMinSize) { + rect.Empty(); + return; + } + FX_FLOAT fBottom = m_rtThumb.bottom(); + FX_FLOAT fRight = m_rtThumb.right(); + FX_FLOAT ix = (m_rtThumb.left + fRight) / 2; + FX_FLOAT iy = (m_rtThumb.top + fBottom) / 2; + rect.left = m_rtClient.left; + rect.top = m_rtClient.top; + FX_BOOL bVertical = IsVertical(); + rect.width = bVertical ? m_rtClient.width : ix; + rect.height = bVertical ? iy : m_rtClient.height; + if (m_bCustomLayout) { + if (bVertical) { + if (0 == m_rtMinBtn.height && 0 == m_rtMaxBtn.height) { + rect.top = m_rtClient.top; + } else if (m_rtMinBtn.top < m_rtThumb.top) { + rect.top = m_rtMinBtn.bottom(); + rect.height -= (m_rtMinBtn.bottom() - m_rtClient.top); + } + } else { + if (0 == m_rtMinBtn.width && 0 == m_rtMaxBtn.width) { + rect.left = m_rtClient.left; + } else if (m_rtMinBtn.left < m_rtThumb.left) { + rect.left = m_rtMinBtn.right(); + rect.width -= (m_rtMinBtn.right() - m_rtClient.left); + } + } + } +} +void CFWL_ScrollBarImp::CalcMaxTrackRect(CFX_RectF& rect) { + if (m_bMinSize) { + rect.Empty(); + return; + } + FX_FLOAT ix = (m_rtThumb.left + m_rtThumb.right()) / 2; + FX_FLOAT iy = (m_rtThumb.top + m_rtThumb.bottom()) / 2; + FX_BOOL bVertical = IsVertical(); + rect.left = bVertical ? m_rtClient.left : ix; + rect.top = bVertical ? iy : m_rtClient.top; + rect.width = bVertical ? m_rtClient.width : m_rtClient.right() - ix; + rect.height = bVertical ? m_rtClient.bottom() - iy : m_rtClient.height; + if (m_bCustomLayout) { + if (bVertical) { + if (m_rtMinBtn.top > m_rtThumb.top && m_rtMinBtn.height > 0 && + m_rtMaxBtn.height > 0) { + rect.height -= (m_rtClient.bottom() - m_rtMinBtn.top); + } else if (m_rtMinBtn.height > 0 && m_rtMaxBtn.height > 0) { + rect.height -= (m_rtClient.bottom() - m_rtMaxBtn.top); + } + } else { + if (m_rtMinBtn.left > m_rtThumb.left && m_rtMinBtn.width > 0 && + m_rtMaxBtn.width > 0) { + rect.width -= (m_rtClient.right() - m_rtMinBtn.left); + } else if (m_rtMinBtn.width > 0 && m_rtMaxBtn.width > 0) { + rect.width -= (m_rtClient.right() - m_rtMaxBtn.left); + } + } + } +} +FX_FLOAT CFWL_ScrollBarImp::GetTrackPointPos(FX_FLOAT fx, FX_FLOAT fy) { + FX_FLOAT fDiffX = fx - m_cpTrackPointX; + FX_FLOAT fDiffY = fy - m_cpTrackPointY; + FX_FLOAT fRange = m_fRangeMax - m_fRangeMin; + FX_FLOAT fPos; + if (m_bCustomLayout) { + if (IsVertical()) { + if (0 == m_rtMinBtn.height && 0 == m_rtMaxBtn.height) { + fPos = fRange * fDiffY / (m_rtClient.height - m_rtThumb.height); + } else if (m_rtMinBtn.bottom() == m_rtMaxBtn.top) { + fPos = fRange * fDiffY / + (m_rtMinBtn.top - m_rtClient.top - m_rtThumb.height); + } else { + fPos = fRange * fDiffY / + (m_rtMaxBtn.top - m_rtMinBtn.bottom() - m_rtThumb.height); + } + } else { + if (0 == m_rtMinBtn.width && 0 == m_rtMaxBtn.width) { + fPos = fRange * fDiffX / (m_rtClient.width - m_rtThumb.width); + } else if (m_rtMinBtn.right() == m_rtMaxBtn.left) { + fPos = fRange * fDiffX / + (m_rtMinBtn.left - m_rtClient.left - m_rtThumb.width); + } else { + fPos = fRange * fDiffX / + (m_rtMaxBtn.left - m_rtMinBtn.right() - m_rtThumb.width); + } + } + } else { + if (IsVertical()) { + fPos = fRange * fDiffY / + (m_rtMaxBtn.top - m_rtMinBtn.bottom() - m_rtThumb.height); + } else { + fPos = fRange * fDiffX / + (m_rtMaxBtn.left - m_rtMinBtn.right() - m_rtThumb.width); + } + } + fPos += m_fLastTrackPos; + if (fPos < m_fRangeMin) { + fPos = m_fRangeMin; + } + if (fPos > m_fRangeMax) { + fPos = m_fRangeMax; + } + return fPos; +} +void CFWL_ScrollBarImp::GetTrackRect(CFX_RectF& rect, FX_BOOL bLower) { + FX_BOOL bDisabled = m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled; + if (bDisabled || m_bCustomLayout) { + rect = bLower ? m_rtMinTrack : m_rtMaxTrack; + } else { + FX_FLOAT fW = m_rtThumb.width / 2; + FX_FLOAT fH = m_rtThumb.height / 2; + FX_BOOL bVert = IsVertical(); + if (bLower) { + if (bVert) { + FX_FLOAT fMinTrackHeight = m_rtMinTrack.height - fH - m_rtMinBtn.height; + fMinTrackHeight = (fMinTrackHeight >= 0.0f) ? fMinTrackHeight : 0.0f; + rect.Set(m_rtMinTrack.left, m_rtMinTrack.top + m_rtMinBtn.height, + m_rtMinTrack.width, fMinTrackHeight); + } else { + FX_FLOAT fMinTrackWidth = + m_rtMinTrack.width - fW - m_rtMinBtn.width + 2; + fMinTrackWidth = (fMinTrackWidth >= 0.0f) ? fMinTrackWidth : 0.0f; + rect.Set(m_rtMinTrack.left + m_rtMinBtn.width - 1, m_rtMinTrack.top, + fMinTrackWidth, m_rtMinTrack.height); + } + } else { + if (bVert) { + FX_FLOAT fMaxTrackHeight = m_rtMaxTrack.height - fH - m_rtMaxBtn.height; + fMaxTrackHeight = (fMaxTrackHeight >= 0.0f) ? fMaxTrackHeight : 0.0f; + rect.Set(m_rtMaxTrack.left, m_rtMaxTrack.top + fH, m_rtMaxTrack.width, + fMaxTrackHeight); + } else { + FX_FLOAT fMaxTrackWidth = + m_rtMaxTrack.width - fW - m_rtMaxBtn.width + 2; + fMaxTrackWidth = (fMaxTrackWidth >= 0.0f) ? fMaxTrackWidth : 0.0f; + rect.Set(m_rtMaxTrack.left + fW, m_rtMaxTrack.top, fMaxTrackWidth, + m_rtMaxTrack.height); + } + } + } +} +FX_BOOL CFWL_ScrollBarImp::SendEvent() { + if (m_iMinButtonState == FWL_PARTSTATE_SCB_Pressed) { + DoScroll(FWL_SCBCODE_StepBackward, m_fTrackPos); + return FALSE; + } + if (m_iMaxButtonState == FWL_PARTSTATE_SCB_Pressed) { + DoScroll(FWL_SCBCODE_StepForward, m_fTrackPos); + return FALSE; + } + if (m_iMinTrackState == FWL_PARTSTATE_SCB_Pressed) { + DoScroll(FWL_SCBCODE_PageBackward, m_fTrackPos); + return m_rtThumb.Contains(m_cpTrackPointX, m_cpTrackPointY); + } + if (m_iMaxTrackState == FWL_PARTSTATE_SCB_Pressed) { + DoScroll(FWL_SCBCODE_PageForward, m_fTrackPos); + return m_rtThumb.Contains(m_cpTrackPointX, m_cpTrackPointY); + } + if (m_iMouseWheel) { + FX_WORD dwCode = + m_iMouseWheel < 0 ? FWL_SCBCODE_StepForward : FWL_SCBCODE_StepBackward; + DoScroll(dwCode, m_fTrackPos); + } + return TRUE; +} +FX_BOOL CFWL_ScrollBarImp::OnScroll(FX_DWORD dwCode, FX_FLOAT fPos) { + FX_BOOL bRet = TRUE; + CFWL_EvtScroll ev; + ev.m_iScrollCode = dwCode; + ev.m_pSrcTarget = m_pInterface; + ev.m_fPos = fPos; + ev.m_pRet = &bRet; + DispatchEvent(&ev); + return bRet; +} +CFWL_ScrollBarImpDelegate::CFWL_ScrollBarImpDelegate(CFWL_ScrollBarImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_ScrollBarImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + if (!pMessage) + return 0; + int32_t iRet = 1; + FX_DWORD dwMsgCode = pMessage->GetClassID(); + if (dwMsgCode == 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->m_dwFlags, pMsg->m_fx, pMsg->m_fy); + break; + } + case FWL_MSGMOUSECMD_LButtonUp: { + OnLButtonUp(pMsg->m_dwFlags, pMsg->m_fx, pMsg->m_fy); + break; + } + case FWL_MSGMOUSECMD_MouseMove: { + OnMouseMove(pMsg->m_dwFlags, pMsg->m_fx, pMsg->m_fy); + break; + } + case FWL_MSGMOUSECMD_MouseLeave: { + OnMouseLeave(); + break; + } + default: { iRet = 0; } + } + } else if (dwMsgCode == FWL_MSGHASH_MouseWheel) { + CFWL_MsgMouseWheel* pMsg = static_cast<CFWL_MsgMouseWheel*>(pMessage); + OnMouseWheel(pMsg->m_fx, pMsg->m_fy, pMsg->m_dwFlags, pMsg->m_fDeltaX, + pMsg->m_fDeltaY); + } else { + iRet = 0; + } + return iRet; +} +FWL_ERR CFWL_ScrollBarImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} +void CFWL_ScrollBarImpDelegate::OnLButtonDown(FX_DWORD dwFlags, + FX_FLOAT fx, + FX_FLOAT fy) { + if (!m_pOwner->IsEnabled()) { + return; + } + m_pOwner->m_bMouseDown = TRUE; + m_pOwner->SetGrab(TRUE); + m_pOwner->m_cpTrackPointX = fx; + m_pOwner->m_cpTrackPointY = fy; + m_pOwner->m_fLastTrackPos = m_pOwner->m_fTrackPos; + if (m_pOwner->m_rtMinBtn.Contains(fx, fy)) { + DoMouseDown(0, m_pOwner->m_rtMinBtn, m_pOwner->m_iMinButtonState, fx, fy); + } else { + if (m_pOwner->m_rtThumb.Contains(fx, fy)) { + DoMouseDown(1, m_pOwner->m_rtThumb, m_pOwner->m_iThumbButtonState, fx, + fy); + } else { + if (m_pOwner->m_rtMaxBtn.Contains(fx, fy)) { + DoMouseDown(2, m_pOwner->m_rtMaxBtn, m_pOwner->m_iMaxButtonState, fx, + fy); + } else { + if (m_pOwner->m_rtMinTrack.Contains(fx, fy)) { + DoMouseDown(3, m_pOwner->m_rtMinTrack, m_pOwner->m_iMinTrackState, fx, + fy); + } else { + DoMouseDown(4, m_pOwner->m_rtMaxTrack, m_pOwner->m_iMaxTrackState, fx, + fy); + } + } + } + } + if (!m_pOwner->SendEvent()) { + m_pOwner->m_hTimer = FWL_StartTimer(m_pOwner, FWL_SCROLLBAR_Elapse); + } +} +void CFWL_ScrollBarImpDelegate::OnLButtonUp(FX_DWORD dwFlags, + FX_FLOAT fx, + FX_FLOAT fy) { + FWL_StopTimer(m_pOwner->m_hTimer); + m_pOwner->m_bMouseDown = FALSE; + DoMouseUp(0, m_pOwner->m_rtMinBtn, m_pOwner->m_iMinButtonState, fx, fy); + DoMouseUp(1, m_pOwner->m_rtThumb, m_pOwner->m_iThumbButtonState, fx, fy); + DoMouseUp(2, m_pOwner->m_rtMaxBtn, m_pOwner->m_iMaxButtonState, fx, fy); + DoMouseUp(3, m_pOwner->m_rtMinTrack, m_pOwner->m_iMinTrackState, fx, fy); + DoMouseUp(4, m_pOwner->m_rtMaxTrack, m_pOwner->m_iMaxTrackState, fx, fy); + m_pOwner->SetGrab(FALSE); +} +void CFWL_ScrollBarImpDelegate::OnMouseMove(FX_DWORD dwFlags, + FX_FLOAT fx, + FX_FLOAT fy) { + DoMouseMove(0, m_pOwner->m_rtMinBtn, m_pOwner->m_iMinButtonState, fx, fy); + DoMouseMove(1, m_pOwner->m_rtThumb, m_pOwner->m_iThumbButtonState, fx, fy); + DoMouseMove(2, m_pOwner->m_rtMaxBtn, m_pOwner->m_iMaxButtonState, fx, fy); + DoMouseMove(3, m_pOwner->m_rtMinTrack, m_pOwner->m_iMinTrackState, fx, fy); + DoMouseMove(4, m_pOwner->m_rtMaxTrack, m_pOwner->m_iMaxTrackState, fx, fy); +} +void CFWL_ScrollBarImpDelegate::OnMouseLeave() { + DoMouseLeave(0, m_pOwner->m_rtMinBtn, m_pOwner->m_iMinButtonState); + DoMouseLeave(1, m_pOwner->m_rtThumb, m_pOwner->m_iThumbButtonState); + DoMouseLeave(2, m_pOwner->m_rtMaxBtn, m_pOwner->m_iMaxButtonState); + DoMouseLeave(3, m_pOwner->m_rtMinTrack, m_pOwner->m_iMinTrackState); + DoMouseLeave(4, m_pOwner->m_rtMaxTrack, m_pOwner->m_iMaxTrackState); +} +void CFWL_ScrollBarImpDelegate::OnMouseWheel(FX_FLOAT fx, + FX_FLOAT fy, + FX_DWORD dwFlags, + FX_FLOAT fDeltaX, + FX_FLOAT fDeltaY) { + m_pOwner->m_iMouseWheel = (int32_t)fDeltaX; + m_pOwner->SendEvent(); + m_pOwner->m_iMouseWheel = 0; +} +void CFWL_ScrollBarImpDelegate::DoMouseDown(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState, + FX_FLOAT fx, + FX_FLOAT fy) { + if (!rtItem.Contains(fx, fy)) { + return; + } + if (iState == FWL_PARTSTATE_SCB_Pressed) { + return; + } + iState = FWL_PARTSTATE_SCB_Pressed; + m_pOwner->Repaint(&rtItem); +} +void CFWL_ScrollBarImpDelegate::DoMouseUp(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState, + FX_FLOAT fx, + FX_FLOAT fy) { + int32_t iNewState = rtItem.Contains(fx, fy) ? FWL_PARTSTATE_SCB_Hovered + : FWL_PARTSTATE_SCB_Normal; + if (iState == iNewState) { + return; + } + iState = iNewState; + m_pOwner->Repaint(&rtItem); + m_pOwner->OnScroll(FWL_SCBCODE_EndScroll, m_pOwner->m_fTrackPos); +} +void CFWL_ScrollBarImpDelegate::DoMouseMove(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState, + FX_FLOAT fx, + FX_FLOAT fy) { + if (!m_pOwner->m_bMouseDown) { + int32_t iNewState = rtItem.Contains(fx, fy) ? FWL_PARTSTATE_SCB_Hovered + : FWL_PARTSTATE_SCB_Normal; + if (iState == iNewState) { + return; + } + iState = iNewState; + m_pOwner->Repaint(&rtItem); + } else if ((2 == iItem) && + (m_pOwner->m_iThumbButtonState == FWL_PARTSTATE_SCB_Pressed)) { + FX_FLOAT fPos = m_pOwner->GetTrackPointPos(fx, fy); + m_pOwner->m_fTrackPos = fPos; + m_pOwner->OnScroll(FWL_SCBCODE_TrackPos, fPos); + } +} +void CFWL_ScrollBarImpDelegate::DoMouseLeave(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState) { + if (iState == FWL_PARTSTATE_SCB_Normal) { + return; + } + iState = FWL_PARTSTATE_SCB_Normal; + m_pOwner->Repaint(&rtItem); +} +void CFWL_ScrollBarImpDelegate::DoMouseHover(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState) { + if (iState == FWL_PARTSTATE_SCB_Hovered) { + return; + } + iState = FWL_PARTSTATE_SCB_Hovered; + m_pOwner->Repaint(&rtItem); +} diff --git a/xfa/src/fwl/basewidget/fwl_scrollbarimp.h b/xfa/src/fwl/basewidget/fwl_scrollbarimp.h new file mode 100644 index 0000000000..be1f25470e --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_scrollbarimp.h @@ -0,0 +1,139 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_SCROLLBARIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_SCROLLBARIMP_H_ + +#include "xfa/include/fwl/core/fwl_timer.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_ScrollBarImpDelegate; + +class CFWL_ScrollBarImp : public CFWL_WidgetImp, public IFWL_Timer { + public: + CFWL_ScrollBarImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_ScrollBarImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual FX_BOOL IsVertical(); + virtual FWL_ERR GetRange(FX_FLOAT& fMin, FX_FLOAT& fMax); + virtual FWL_ERR SetRange(FX_FLOAT fMin, FX_FLOAT fMax); + virtual FX_FLOAT GetPageSize(); + virtual FWL_ERR SetPageSize(FX_FLOAT fPageSize); + virtual FX_FLOAT GetStepSize(); + virtual FWL_ERR SetStepSize(FX_FLOAT fStepSize); + virtual FX_FLOAT GetPos(); + virtual FWL_ERR SetPos(FX_FLOAT fPos); + virtual FX_FLOAT GetTrackPos(); + virtual FWL_ERR SetTrackPos(FX_FLOAT fTrackPos); + virtual FX_BOOL DoScroll(FX_DWORD dwCode, FX_FLOAT fPos = 0.0f); + virtual FWL_ERR SetOuter(IFWL_Widget* pOuter); + virtual int32_t Run(FWL_HTIMER hTimer); + + protected: + void DrawTrack(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + FX_BOOL bLower = TRUE, + const CFX_Matrix* pMatrix = NULL); + void DrawArrowBtn(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + FX_BOOL bMinBtn = TRUE, + const CFX_Matrix* pMatrix = NULL); + void DrawThumb(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix = NULL); + void Layout(); + void CalcButtonLen(); + void CalcMinButtonRect(CFX_RectF& rect); + void CalcMaxButtonRect(CFX_RectF& rect); + void CalcThumbButtonRect(CFX_RectF& rect); + void CalcMinTrackRect(CFX_RectF& rect); + void CalcMaxTrackRect(CFX_RectF& rect); + FX_FLOAT GetTrackPointPos(FX_FLOAT fx, FX_FLOAT fy); + void GetTrackRect(CFX_RectF& rect, FX_BOOL bLower = TRUE); + FX_BOOL SendEvent(); + FX_BOOL OnScroll(FX_DWORD dwCode, FX_FLOAT fPos); + + FWL_HTIMER m_hTimer; + FX_FLOAT m_fRangeMin; + FX_FLOAT m_fRangeMax; + FX_FLOAT m_fPageSize; + FX_FLOAT m_fStepSize; + FX_FLOAT m_fPos; + FX_FLOAT m_fTrackPos; + int32_t m_iMinButtonState; + int32_t m_iMaxButtonState; + int32_t m_iThumbButtonState; + int32_t m_iMinTrackState; + int32_t m_iMaxTrackState; + FX_FLOAT m_fLastTrackPos; + FX_FLOAT m_cpTrackPointX; + FX_FLOAT m_cpTrackPointY; + int32_t m_iMouseWheel; + FX_BOOL m_bTrackMouseLeave; + FX_BOOL m_bMouseHover; + FX_BOOL m_bMouseDown; + FX_BOOL m_bRepaintThumb; + FX_FLOAT m_fButtonLen; + FX_BOOL m_bMinSize; + CFX_RectF m_rtClient; + CFX_RectF m_rtThumb; + CFX_RectF m_rtMinBtn; + CFX_RectF m_rtMaxBtn; + CFX_RectF m_rtMinTrack; + CFX_RectF m_rtMaxTrack; + FX_BOOL m_bCustomLayout; + FX_FLOAT m_fMinThumb; + friend class CFWL_ScrollBarImpDelegate; +}; +class CFWL_ScrollBarImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_ScrollBarImpDelegate(CFWL_ScrollBarImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy); + void OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy); + void OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy); + void OnMouseLeave(); + void OnMouseWheel(FX_FLOAT fx, + FX_FLOAT fy, + FX_DWORD dwFlags, + FX_FLOAT fDeltaX, + FX_FLOAT fDeltaY); + void DoMouseDown(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState, + FX_FLOAT fx, + FX_FLOAT fy); + void DoMouseUp(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState, + FX_FLOAT fx, + FX_FLOAT fy); + void DoMouseMove(int32_t iItem, + const CFX_RectF& rtItem, + int32_t& iState, + FX_FLOAT fx, + FX_FLOAT fy); + void DoMouseLeave(int32_t iItem, const CFX_RectF& rtItem, int32_t& iState); + void DoMouseHover(int32_t iItem, const CFX_RectF& rtItem, int32_t& iState); + + CFWL_ScrollBarImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_SCROLLBARIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_spinbuttonimp.cpp b/xfa/src/fwl/basewidget/fwl_spinbuttonimp.cpp new file mode 100644 index 0000000000..fd7c226102 --- /dev/null +++ b/xfa/src/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/src/fwl/basewidget/fwl_spinbuttonimp.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" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.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); +} diff --git a/xfa/src/fwl/basewidget/fwl_spinbuttonimp.h b/xfa/src/fwl/basewidget/fwl_spinbuttonimp.h new file mode 100644 index 0000000000..769db28c30 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_spinbuttonimp.h @@ -0,0 +1,69 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_SPINBUTTONIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_SPINBUTTONIMP_H_ + +#include "xfa/include/fwl/core/fwl_timer.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class CFWL_SpinButtonImpDelegate; + +class CFWL_SpinButtonImp : public CFWL_WidgetImp, public IFWL_Timer { + public: + CFWL_SpinButtonImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + ~CFWL_SpinButtonImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FX_DWORD HitTest(FX_FLOAT fx, FX_FLOAT fy); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual int32_t Run(FWL_HTIMER hTimer); + FWL_ERR EnableButton(FX_BOOL bEnable, FX_BOOL bUp = TRUE); + FX_BOOL IsButtonEnable(FX_BOOL bUp = TRUE); + + protected: + void DrawUpButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawDownButton(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + CFX_RectF m_rtClient; + CFX_RectF m_rtUpButton; + CFX_RectF m_rtDnButton; + FX_DWORD m_dwUpState; + FX_DWORD m_dwDnState; + int32_t m_iButtonIndex; + FX_BOOL m_bLButtonDwn; + FWL_HTIMER m_hTimer; + friend class CFWL_SpinButtonImpDelegate; +}; +class CFWL_SpinButtonImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_SpinButtonImpDelegate(CFWL_SpinButtonImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + void OnKeyDown(CFWL_MsgKey* pMsg); + CFWL_SpinButtonImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_SPINBUTTONIMP_H_ diff --git a/xfa/src/fwl/basewidget/fwl_tooltipctrlimp.cpp b/xfa/src/fwl/basewidget/fwl_tooltipctrlimp.cpp new file mode 100644 index 0000000000..63966ba4c8 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_tooltipctrlimp.cpp @@ -0,0 +1,293 @@ +// 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/src/fwl/basewidget/fwl_tooltipctrlimp.h" + +#include "xfa/include/fwl/basewidget/fwl_tooltipctrl.h" +#include "xfa/include/fwl/core/fwl_theme.h" +#include "xfa/src/fdp/include/fde_tto.h" +#include "xfa/src/fwl/core/fwl_formimp.h" +#include "xfa/src/fwl/core/fwl_noteimp.h" +#include "xfa/src/fwl/core/fwl_panelimp.h" +#include "xfa/src/fwl/core/fwl_targetimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +// static +IFWL_ToolTip* IFWL_ToolTip::Create(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) { + IFWL_ToolTip* pToolTip = new IFWL_ToolTip; + CFWL_ToolTipImp* pToolTipImpl = new CFWL_ToolTipImp(properties, pOuter); + pToolTip->SetImpl(pToolTipImpl); + pToolTipImpl->SetInterface(pToolTip); + return pToolTip; +} +FWL_ERR IFWL_ToolTip::SetAnchor(const CFX_RectF& rtAnchor) { + return static_cast<CFWL_ToolTipImp*>(GetImpl())->SetAnchor(rtAnchor); +} +FWL_ERR IFWL_ToolTip::Show() { + return static_cast<CFWL_ToolTipImp*>(GetImpl())->Show(); +} +FWL_ERR IFWL_ToolTip::Hide() { + return static_cast<CFWL_ToolTipImp*>(GetImpl())->Hide(); +} +IFWL_ToolTip::IFWL_ToolTip() {} +CFWL_ToolTipImp::CFWL_ToolTipImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter) + : CFWL_FormImp(properties, pOuter), + m_bBtnDown(FALSE), + m_dwTTOStyles(FDE_TTOSTYLE_SingleLine), + m_iTTOAlign(FDE_TTOALIGNMENT_Center), + m_hTimerShow(NULL), + m_hTimerHide(NULL), + m_pTimer(NULL) { + m_rtClient.Set(0, 0, 0, 0); + m_rtCaption.Set(0, 0, 0, 0); + m_rtAnchor.Set(0, 0, 0, 0); + m_TimerShow.m_pToolTip = this; + m_TimerHide.m_pToolTip = this; +} +CFWL_ToolTipImp::~CFWL_ToolTipImp() { + if (m_pTimer) { + delete m_pTimer; + m_pTimer = NULL; + } +} +FWL_ERR CFWL_ToolTipImp::GetClassName(CFX_WideString& wsClass) const { + wsClass = FWL_CLASS_ToolTip; + return FWL_ERR_Succeeded; +} +FX_DWORD CFWL_ToolTipImp::GetClassID() const { + return FWL_CLASSHASH_ToolTip; +} +FWL_ERR CFWL_ToolTipImp::Initialize() { + m_pProperties->m_dwStyles |= FWL_WGTSTYLE_Popup; + m_pProperties->m_dwStyles &= ~FWL_WGTSTYLE_Child; + if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) + return FWL_ERR_Indefinite; + m_pDelegate = new CFWL_ToolTipImpDelegate(this); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ToolTipImp::Finalize() { + delete m_pDelegate; + m_pDelegate = nullptr; + return CFWL_WidgetImp::Finalize(); +} +FWL_ERR CFWL_ToolTipImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { + if (bAutoSize) { + rect.Set(0, 0, 0, 0); + if (m_pProperties->m_pThemeProvider == NULL) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + CFX_WideString wsCaption; + IFWL_ToolTipDP* pData = + static_cast<IFWL_ToolTipDP*>(m_pProperties->m_pDataProvider); + if (pData) { + pData->GetCaption(m_pInterface, wsCaption); + } + int32_t iLen = wsCaption.GetLength(); + if (iLen > 0) { + CFX_SizeF sz = CalcTextSize(wsCaption, m_pProperties->m_pThemeProvider); + rect.Set(0, 0, sz.x, sz.y); + rect.width += FWL_WGTCAPACITY_CXBorder * 25; + rect.height += FWL_WGTCAPACITY_CYBorder * 8; + } + CFWL_WidgetImp::GetWidgetRect(rect, TRUE); + } else { + rect = m_pProperties->m_rtWidget; + } + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ToolTipImp::Update() { + if (IsLocked()) { + return FWL_ERR_Indefinite; + } + if (!m_pProperties->m_pThemeProvider) { + m_pProperties->m_pThemeProvider = GetAvailableTheme(); + } + UpdateTextOutStyles(); + GetClientRect(m_rtClient); + m_rtCaption = m_rtClient; + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ToolTipImp::GetClientRect(CFX_RectF& rect) { + FX_FLOAT x = 0; + FX_FLOAT y = 0; + FX_FLOAT t = 0; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + if (pTheme) { + CFWL_ThemePart part; + part.m_pWidget = m_pInterface; + x = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CXBorder)); + y = *static_cast<FX_FLOAT*>( + pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CYBorder)); + } + rect = m_pProperties->m_rtWidget; + rect.Offset(-rect.left, -rect.top); + rect.Deflate(x, t, x, y); + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ToolTipImp::DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + IFWL_ToolTipTarget* toolTipTarget = + CFWL_ToolTipContainer::getInstance()->GetCurrentToolTipTarget(); + if (toolTipTarget && !toolTipTarget->UseDefaultTheme()) { + return toolTipTarget->DrawToolTip(pGraphics, pMatrix, m_pInterface); + } + if (!pGraphics) + return FWL_ERR_Indefinite; + if (!m_pProperties->m_pThemeProvider) + return FWL_ERR_Indefinite; + IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; + DrawBkground(pGraphics, pTheme, pMatrix); + DrawText(pGraphics, pTheme, pMatrix); + return FWL_ERR_Succeeded; +} +void CFWL_ToolTipImp::DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + CFWL_ThemeBackground param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_TTP_Background; + param.m_dwStates = m_pProperties->m_dwStates; + param.m_pGraphics = pGraphics; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = m_rtClient; + if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { + param.m_pData = &m_rtCaption; + } + pTheme->DrawBackground(¶m); +} +void CFWL_ToolTipImp::DrawText(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix) { + if (!m_pProperties->m_pDataProvider) + return; + CFX_WideString wsCaption; + m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption); + if (wsCaption.IsEmpty()) { + return; + } + CFWL_ThemeText param; + param.m_pWidget = m_pInterface; + param.m_iPart = FWL_PART_TTP_Caption; + param.m_dwStates = m_pProperties->m_dwStates; + param.m_pGraphics = pGraphics; + if (pMatrix) { + param.m_matrix.Concat(*pMatrix); + } + param.m_rtPart = m_rtCaption; + param.m_wsText = wsCaption; + param.m_dwTTOStyles = m_dwTTOStyles; + param.m_iTTOAlign = m_iTTOAlign; + pTheme->DrawText(¶m); +} +void CFWL_ToolTipImp::UpdateTextOutStyles() { + m_iTTOAlign = FDE_TTOALIGNMENT_Center; + m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; + if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) { + m_dwTTOStyles |= FDE_TTOSTYLE_RTL; + } + if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_TTP_Multiline) { + m_dwTTOStyles &= ~FDE_TTOSTYLE_SingleLine; + } +} +FWL_ERR CFWL_ToolTipImp::SetAnchor(const CFX_RectF& rtAnchor) { + m_rtAnchor = rtAnchor; + return TRUE; +} +FWL_ERR CFWL_ToolTipImp::Show() { + IFWL_ToolTipDP* pData = + static_cast<IFWL_ToolTipDP*>(m_pProperties->m_pDataProvider); + int32_t nInitDelay = pData->GetInitialDelay(m_pInterface); + if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible)) { + m_hTimerShow = FWL_StartTimer(&m_TimerShow, nInitDelay, FALSE); + } + return TRUE; +} +FWL_ERR CFWL_ToolTipImp::Hide() { + SetStates(FWL_WGTSTATE_Invisible, TRUE); + if (m_hTimerHide) { + FWL_StopTimer(m_hTimerHide); + m_hTimerHide = NULL; + } + if (m_hTimerShow) { + FWL_StopTimer(m_hTimerShow); + m_hTimerShow = NULL; + } + return TRUE; +} +FWL_ERR CFWL_ToolTipImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) { + if ((dwStates & FWL_WGTSTATE_Invisible) && !bSet) { + IFWL_ToolTipDP* pData = + static_cast<IFWL_ToolTipDP*>(m_pProperties->m_pDataProvider); + int32_t nAutoPopDelay = pData->GetAutoPopDelay(m_pInterface); + m_hTimerHide = FWL_StartTimer(&m_TimerHide, nAutoPopDelay, FALSE); + } + return CFWL_WidgetImp::SetStates(dwStates, bSet); +} +void CFWL_ToolTipImp::RefreshToolTipPos() { + if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_TTP_NoAnchor) == 0) { + CFX_RectF rtPopup; + CFX_RectF rtWidget(m_pProperties->m_rtWidget); + CFX_RectF rtAnchor(m_rtAnchor); + rtPopup.Set(0, 0, 0, 0); + FX_FLOAT fx = rtAnchor.Center().x + 20; + FX_FLOAT fy = rtAnchor.Center().y + 20; + rtPopup.Set(fx, fy, rtWidget.Width(), rtWidget.Height()); + FX_FLOAT fScreenWidth = 0; + FX_FLOAT fScreenHeight = 0; + GetScreenSize(fScreenWidth, fScreenHeight); + if (rtPopup.bottom() > fScreenHeight) { + rtPopup.Offset(0, fScreenHeight - rtPopup.bottom()); + } + if (rtPopup.right() > fScreenWidth) { + rtPopup.Offset(fScreenWidth - rtPopup.right(), 0); + } + if (rtPopup.left < 0) { + rtPopup.Offset(0 - rtPopup.left, 0); + } + if (rtPopup.top < 0) { + rtPopup.Offset(0, 0 - rtPopup.top); + } + SetWidgetRect(rtPopup); + Update(); + } +} +CFWL_ToolTipImp::CFWL_ToolTipTimer::CFWL_ToolTipTimer(CFWL_ToolTipImp* pToolTip) + : m_pToolTip(pToolTip) {} +int32_t CFWL_ToolTipImp::CFWL_ToolTipTimer::Run(FWL_HTIMER hTimer) { + if (m_pToolTip->m_hTimerShow == hTimer && m_pToolTip->m_hTimerShow) { + if (m_pToolTip->GetStates() & FWL_WGTSTATE_Invisible) { + m_pToolTip->SetStates(FWL_WGTSTATE_Invisible, FALSE); + m_pToolTip->RefreshToolTipPos(); + FWL_StopTimer(m_pToolTip->m_hTimerShow); + m_pToolTip->m_hTimerShow = NULL; + return TRUE; + } + } + if (m_pToolTip->m_hTimerHide == hTimer && m_pToolTip->m_hTimerHide) { + m_pToolTip->SetStates(FWL_WGTSTATE_Invisible, TRUE); + FWL_StopTimer(m_pToolTip->m_hTimerHide); + m_pToolTip->m_hTimerHide = NULL; + return TRUE; + } + return TRUE; +} +CFWL_ToolTipImpDelegate::CFWL_ToolTipImpDelegate(CFWL_ToolTipImp* pOwner) + : m_pOwner(pOwner) {} +int32_t CFWL_ToolTipImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { + return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); +} +FWL_ERR CFWL_ToolTipImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { + return FWL_ERR_Succeeded; +} +FWL_ERR CFWL_ToolTipImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix) { + return m_pOwner->DrawWidget(pGraphics, pMatrix); +} diff --git a/xfa/src/fwl/basewidget/fwl_tooltipctrlimp.h b/xfa/src/fwl/basewidget/fwl_tooltipctrlimp.h new file mode 100644 index 0000000000..08fb7b0639 --- /dev/null +++ b/xfa/src/fwl/basewidget/fwl_tooltipctrlimp.h @@ -0,0 +1,86 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FWL_TOOLTIPCTRLIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FWL_TOOLTIPCTRLIMP_H_ + +#include "xfa/include/fwl/core/fwl_timer.h" +#include "xfa/src/fwl/core/fwl_formimp.h" +#include "xfa/src/fwl/core/fwl_widgetimp.h" + +class CFWL_WidgetImpProperties; +class IFWL_Widget; +class CFWL_ToolTipImpDelegate; + +class CFWL_ToolTipImp : public CFWL_FormImp { + public: + CFWL_ToolTipImp(const CFWL_WidgetImpProperties& properties, + IFWL_Widget* pOuter); + virtual ~CFWL_ToolTipImp(); + virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const; + virtual FX_DWORD GetClassID() const; + virtual FWL_ERR Initialize(); + virtual FWL_ERR Finalize(); + virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE); + virtual FWL_ERR Update(); + virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL); + virtual FWL_ERR SetStates(FX_DWORD dwStates, FX_BOOL bSet); + virtual FWL_ERR GetClientRect(CFX_RectF& rect); + FWL_ERR SetAnchor(const CFX_RectF& rtAnchor); + FWL_ERR Show(); + FWL_ERR Hide(); + + protected: + void DrawBkground(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void DrawText(CFX_Graphics* pGraphics, + IFWL_ThemeProvider* pTheme, + const CFX_Matrix* pMatrix); + void UpdateTextOutStyles(); + void RefreshToolTipPos(); + class CFWL_ToolTipTimer : public IFWL_Timer { + public: + CFWL_ToolTipTimer() {} + ~CFWL_ToolTipTimer() {} + CFWL_ToolTipTimer(CFWL_ToolTipImp* pToolTip); + virtual int32_t Run(FWL_HTIMER hTimer); + CFWL_ToolTipImp* m_pToolTip; + }; + CFX_RectF m_rtClient; + CFX_RectF m_rtCaption; + FX_BOOL m_bBtnDown; + FX_DWORD m_dwTTOStyles; + int32_t m_iTTOAlign; + CFX_RectF m_rtAnchor; + FWL_HTIMER m_hTimerShow; + FWL_HTIMER m_hTimerHide; + CFWL_ToolTipTimer* m_pTimer; + CFWL_ToolTipTimer m_TimerShow; + CFWL_ToolTipTimer m_TimerHide; + friend class CFWL_ToolTipImpDelegate; + friend class CFWL_ToolTipTimer; +}; +class CFWL_ToolTipImpDelegate : public CFWL_WidgetImpDelegate { + public: + CFWL_ToolTipImpDelegate(CFWL_ToolTipImp* pOwner); + int32_t OnProcessMessage(CFWL_Message* pMessage) override; + FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override; + FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics, + const CFX_Matrix* pMatrix = NULL) override; + + protected: + void OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet = TRUE); + void OnLButtonDown(CFWL_MsgMouse* pMsg); + void OnLButtonUp(CFWL_MsgMouse* pMsg); + void OnMouseMove(CFWL_MsgMouse* pMsg); + void OnMouseLeave(CFWL_MsgMouse* pMsg); + void OnKeyDown(CFWL_MsgKey* pMsg); + CFWL_ToolTipImp* m_pOwner; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FWL_TOOLTIPCTRLIMP_H_ diff --git a/xfa/src/fwl/basewidget/fxmath_barcodeimp.cpp b/xfa/src/fwl/basewidget/fxmath_barcodeimp.cpp new file mode 100644 index 0000000000..8c9bfe432c --- /dev/null +++ b/xfa/src/fwl/basewidget/fxmath_barcodeimp.cpp @@ -0,0 +1,385 @@ +// 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/src/fwl/basewidget/fxmath_barcodeimp.h" + +static CBC_CodeBase* FX_Barcode_CreateBarCodeEngineObject(BC_TYPE type) { + switch (type) { + case BC_CODE39: + return new CBC_Code39(); + case BC_CODABAR: + return new CBC_Codabar(); + case BC_CODE128: + return new CBC_Code128(BC_CODE128_B); + case BC_CODE128_B: + return new CBC_Code128(BC_CODE128_B); + case BC_CODE128_C: + return new CBC_Code128(BC_CODE128_C); + case BC_EAN8: + return new CBC_EAN8(); + case BC_UPCA: + return new CBC_UPCA(); + case BC_EAN13: + return new CBC_EAN13(); + case BC_QR_CODE: + return new CBC_QRCode(); + case BC_PDF417: + return new CBC_PDF417I(); + case BC_DATAMATRIX: + return new CBC_DataMatrix(); + case BC_UNKNOWN: + default: + return NULL; + } +} +CFX_Barcode::CFX_Barcode() {} +CFX_Barcode::~CFX_Barcode() { + if (m_pBCEngine) { + delete m_pBCEngine; + m_pBCEngine = NULL; + } +} +FX_BOOL CFX_Barcode::Crreate(BC_TYPE type) { + m_pBCEngine = FX_Barcode_CreateBarCodeEngineObject(type); + return m_pBCEngine != NULL; +} +void CFX_Barcode::Release() { + delete this; +} +BC_TYPE CFX_Barcode::GetType() { + return m_pBCEngine ? m_pBCEngine->GetType() : BC_UNKNOWN; +} +FX_BOOL CFX_Barcode::SetCharEncoding(BC_CHAR_ENCODING encoding) { + return m_pBCEngine ? m_pBCEngine->SetCharEncoding(encoding) : FALSE; +} +FX_BOOL CFX_Barcode::SetModuleHeight(int32_t moduleHeight) { + return m_pBCEngine ? m_pBCEngine->SetModuleHeight(moduleHeight) : FALSE; +} +FX_BOOL CFX_Barcode::SetModuleWidth(int32_t moduleWidth) { + return m_pBCEngine ? m_pBCEngine->SetModuleWidth(moduleWidth) : FALSE; +} +FX_BOOL CFX_Barcode::SetHeight(int32_t height) { + return m_pBCEngine ? m_pBCEngine->SetHeight(height) : FALSE; +} +FX_BOOL CFX_Barcode::SetWidth(int32_t width) { + return m_pBCEngine ? m_pBCEngine->SetWidth(width) : FALSE; +} +FX_BOOL CFX_Barcode::CheckContentValidity(const CFX_WideStringC& contents) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine + ? static_cast<CBC_OneCode*>(m_pBCEngine) + ->CheckContentValidity(contents) + : TRUE; + default: + return TRUE; + } +} +FX_BOOL CFX_Barcode::SetPrintChecksum(FX_BOOL checksum) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine) + ->SetPrintChecksum(checksum), + TRUE) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetDataLength(int32_t length) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine) + ->SetDataLength(length), + TRUE) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetCalChecksum(int32_t state) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine) + ->SetCalChecksum(state), + TRUE) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetFont(CFX_Font* pFont) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine + ? static_cast<CBC_OneCode*>(m_pBCEngine)->SetFont(pFont) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetFontSize(FX_FLOAT size) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine + ? (static_cast<CBC_OneCode*>(m_pBCEngine)->SetFontSize(size), + TRUE) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetFontStyle(int32_t style) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine + ? (static_cast<CBC_OneCode*>(m_pBCEngine)->SetFontStyle(style), + TRUE) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetFontColor(FX_ARGB color) { + switch (GetType()) { + case BC_CODE39: + case BC_CODABAR: + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + case BC_EAN8: + case BC_EAN13: + case BC_UPCA: + return m_pBCEngine + ? (static_cast<CBC_OneCode*>(m_pBCEngine)->SetFontColor(color), + TRUE) + : FALSE; + default: + return FALSE; + } +} +FX_BOOL CFX_Barcode::SetTextLocation(BC_TEXT_LOC location) { + typedef FX_BOOL (CBC_CodeBase::*memptrtype)(BC_TEXT_LOC); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_CODE39: + memptr = (memptrtype)&CBC_Code39::SetTextLocation; + break; + case BC_CODABAR: + memptr = (memptrtype)&CBC_Codabar::SetTextLocation; + break; + case BC_CODE128: + case BC_CODE128_B: + case BC_CODE128_C: + memptr = (memptrtype)&CBC_Code128::SetTextLocation; + break; + default: + break; + } + return m_pBCEngine && memptr ? (m_pBCEngine->*memptr)(location) : FALSE; +} +FX_BOOL CFX_Barcode::SetWideNarrowRatio(int32_t ratio) { + typedef FX_BOOL (CBC_CodeBase::*memptrtype)(int32_t); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_CODE39: + memptr = (memptrtype)&CBC_Code39::SetWideNarrowRatio; + break; + case BC_CODABAR: + memptr = (memptrtype)&CBC_Codabar::SetWideNarrowRatio; + break; + default: + break; + } + return m_pBCEngine && memptr ? (m_pBCEngine->*memptr)(ratio) : FALSE; +} +FX_BOOL CFX_Barcode::SetStartChar(FX_CHAR start) { + typedef FX_BOOL (CBC_CodeBase::*memptrtype)(FX_CHAR); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_CODABAR: + memptr = (memptrtype)&CBC_Codabar::SetStartChar; + break; + default: + break; + } + return m_pBCEngine && memptr ? (m_pBCEngine->*memptr)(start) : FALSE; +} +FX_BOOL CFX_Barcode::SetEndChar(FX_CHAR end) { + typedef FX_BOOL (CBC_CodeBase::*memptrtype)(FX_CHAR); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_CODABAR: + memptr = (memptrtype)&CBC_Codabar::SetEndChar; + break; + default: + break; + } + return m_pBCEngine && memptr ? (m_pBCEngine->*memptr)(end) : FALSE; +} +FX_BOOL CFX_Barcode::SetVersion(int32_t version) { + typedef FX_BOOL (CBC_CodeBase::*memptrtype)(int32_t); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_QR_CODE: + memptr = (memptrtype)&CBC_QRCode::SetVersion; + break; + default: + break; + } + return m_pBCEngine && memptr ? (m_pBCEngine->*memptr)(version) : FALSE; +} +FX_BOOL CFX_Barcode::SetErrorCorrectionLevel(int32_t level) { + typedef FX_BOOL (CBC_CodeBase::*memptrtype)(int32_t); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_QR_CODE: + memptr = (memptrtype)&CBC_QRCode::SetErrorCorrectionLevel; + break; + case BC_PDF417: + memptr = (memptrtype)&CBC_PDF417I::SetErrorCorrectionLevel; + break; + default: + return FALSE; + } + return m_pBCEngine && memptr ? (m_pBCEngine->*memptr)(level) : FALSE; +} +FX_BOOL CFX_Barcode::SetTruncated(FX_BOOL truncated) { + typedef void (CBC_CodeBase::*memptrtype)(FX_BOOL); + memptrtype memptr = NULL; + switch (GetType()) { + case BC_PDF417: + memptr = (memptrtype)&CBC_PDF417I::SetTruncated; + break; + default: + break; + } + return m_pBCEngine && memptr ? ((m_pBCEngine->*memptr)(truncated), TRUE) + : FALSE; +} +#ifndef BCExceptionNO +#define BCExceptionNO 0 +#endif +#ifndef BCExceptionFormatException +#define BCExceptionFormatException 8 +#endif +#ifndef BCExceptionUnSupportedBarcode +#define BCExceptionUnSupportedBarcode 18 +#endif +FX_BOOL CFX_Barcode::Encode(const CFX_WideStringC& contents, + FX_BOOL isDevice, + int32_t& e) { + if (!m_pBCEngine) { + return FALSE; + } + return m_pBCEngine->Encode(contents, isDevice, e); +} +FX_BOOL CFX_Barcode::RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matirx, + int32_t& e) { + if (!m_pBCEngine) { + return FALSE; + } + return m_pBCEngine->RenderDevice(device, matirx, e); +} +FX_BOOL CFX_Barcode::RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e) { + if (!m_pBCEngine) { + return FALSE; + } + return m_pBCEngine->RenderBitmap(pOutBitmap, e); +} +#define BC_TYPE_MIN BC_CODE39 +#define BC_TYPE_MAX BC_DATAMATRIX +CFX_WideString CFX_Barcode::Decode(uint8_t* buf, + int32_t width, + int32_t height, + int32_t& errorCode) { + for (BC_TYPE t = BC_TYPE_MIN; t <= BC_TYPE_MAX; + t = (BC_TYPE)((int32_t)t + 1)) { + CBC_CodeBase* pTmpEngine = FX_Barcode_CreateBarCodeEngineObject(t); + if (!pTmpEngine) { + continue; + } + CFX_WideString ret = pTmpEngine->Decode(buf, width, height, errorCode); + if (errorCode == BCExceptionNO) { + return ret; + } + } + errorCode = BCExceptionUnSupportedBarcode; + return CFX_WideString(); +} +CFX_WideString CFX_Barcode::Decode(CFX_DIBitmap* pBitmap, int32_t& errorCode) { + for (BC_TYPE t = BC_TYPE_MIN; t <= BC_TYPE_MAX; + t = (BC_TYPE)((int32_t)t + 1)) { + CBC_CodeBase* pTmpEngine = FX_Barcode_CreateBarCodeEngineObject(t); + if (!pTmpEngine) { + continue; + } + CFX_WideString ret = pTmpEngine->Decode(pBitmap, errorCode); + if (errorCode == BCExceptionNO) { + return ret; + } + } + errorCode = BCExceptionUnSupportedBarcode; + return CFX_WideString(); +} +IFX_Barcode* FX_Barcode_Create(BC_TYPE type) { + CFX_Barcode* pBarcode = new CFX_Barcode; + if (pBarcode->Crreate(type)) { + return pBarcode; + } + pBarcode->Release(); + return NULL; +} diff --git a/xfa/src/fwl/basewidget/fxmath_barcodeimp.h b/xfa/src/fwl/basewidget/fxmath_barcodeimp.h new file mode 100644 index 0000000000..22cb97bcc4 --- /dev/null +++ b/xfa/src/fwl/basewidget/fxmath_barcodeimp.h @@ -0,0 +1,56 @@ +// 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 + +#ifndef XFA_SRC_FWL_BASEWIDGET_FXMATH_BARCODEIMP_H_ +#define XFA_SRC_FWL_BASEWIDGET_FXMATH_BARCODEIMP_H_ + +#include "xfa/include/fwl/basewidget/fxmath_barcode.h" + +class CFX_Barcode : public IFX_Barcode { + public: + CFX_Barcode(); + ~CFX_Barcode(); + FX_BOOL Crreate(BC_TYPE type); + virtual void Release(); + virtual BC_TYPE GetType(); + virtual FX_BOOL Encode(const CFX_WideStringC& contents, + FX_BOOL isDevice, + int32_t& e); + virtual FX_BOOL RenderDevice(CFX_RenderDevice* device, + const CFX_Matrix* matirx, + int32_t& e); + virtual FX_BOOL RenderBitmap(CFX_DIBitmap*& pOutBitmap, int32_t& e); + virtual CFX_WideString Decode(uint8_t* buf, + int32_t width, + int32_t height, + int32_t& errorCode); + virtual CFX_WideString Decode(CFX_DIBitmap* pBitmap, int32_t& errorCode); + virtual FX_BOOL SetCharEncoding(BC_CHAR_ENCODING encoding); + virtual FX_BOOL SetModuleHeight(int32_t moduleHeight); + virtual FX_BOOL SetModuleWidth(int32_t moduleWidth); + virtual FX_BOOL SetHeight(int32_t height); + virtual FX_BOOL SetWidth(int32_t width); + virtual FX_BOOL CheckContentValidity(const CFX_WideStringC& contents); + virtual FX_BOOL SetPrintChecksum(FX_BOOL checksum); + virtual FX_BOOL SetDataLength(int32_t length); + virtual FX_BOOL SetCalChecksum(int32_t state); + virtual FX_BOOL SetFont(CFX_Font* pFont); + virtual FX_BOOL SetFontSize(FX_FLOAT size); + virtual FX_BOOL SetFontStyle(int32_t style); + virtual FX_BOOL SetFontColor(FX_ARGB color); + virtual FX_BOOL SetTextLocation(BC_TEXT_LOC location); + virtual FX_BOOL SetWideNarrowRatio(int32_t ratio); + virtual FX_BOOL SetStartChar(FX_CHAR start); + virtual FX_BOOL SetEndChar(FX_CHAR end); + virtual FX_BOOL SetVersion(int32_t version); + virtual FX_BOOL SetErrorCorrectionLevel(int32_t level); + virtual FX_BOOL SetTruncated(FX_BOOL truncated); + + protected: + CBC_CodeBase* m_pBCEngine; +}; + +#endif // XFA_SRC_FWL_BASEWIDGET_FXMATH_BARCODEIMP_H_ |