You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
11 KiB
328 lines
11 KiB
// 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/fxfa/app/xfa_ffcheckbutton.h" |
|
|
|
#include "xfa/fwl/cfwl_checkbox.h" |
|
#include "xfa/fwl/cfwl_messagemouse.h" |
|
#include "xfa/fwl/cfwl_notedriver.h" |
|
#include "xfa/fwl/cfwl_widgetmgr.h" |
|
#include "xfa/fxfa/app/xfa_ffexclgroup.h" |
|
#include "xfa/fxfa/app/xfa_fffield.h" |
|
#include "xfa/fxfa/xfa_ffapp.h" |
|
#include "xfa/fxfa/xfa_ffdoc.h" |
|
#include "xfa/fxfa/xfa_ffdocview.h" |
|
#include "xfa/fxfa/xfa_ffpageview.h" |
|
#include "xfa/fxfa/xfa_ffwidget.h" |
|
|
|
CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_WidgetAcc* pDataAcc) |
|
: CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {} |
|
|
|
CXFA_FFCheckButton::~CXFA_FFCheckButton() {} |
|
|
|
bool CXFA_FFCheckButton::LoadWidget() { |
|
CFWL_CheckBox* pCheckBox = new CFWL_CheckBox(GetFWLApp()); |
|
m_pNormalWidget = pCheckBox; |
|
m_pNormalWidget->SetLayoutItem(this); |
|
|
|
CFWL_NoteDriver* pNoteDriver = |
|
m_pNormalWidget->GetOwnerApp()->GetNoteDriver(); |
|
pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget); |
|
|
|
m_pOldDelegate = m_pNormalWidget->GetDelegate(); |
|
m_pNormalWidget->SetDelegate(this); |
|
|
|
if (m_pDataAcc->IsRadioButton()) |
|
pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF); |
|
|
|
m_pNormalWidget->LockUpdate(); |
|
UpdateWidgetProperty(); |
|
SetFWLCheckState(m_pDataAcc->GetCheckState()); |
|
m_pNormalWidget->UnlockUpdate(); |
|
return CXFA_FFField::LoadWidget(); |
|
} |
|
void CXFA_FFCheckButton::UpdateWidgetProperty() { |
|
CFWL_CheckBox* pCheckBox = (CFWL_CheckBox*)m_pNormalWidget; |
|
if (!m_pNormalWidget) { |
|
return; |
|
} |
|
FX_FLOAT fSize = m_pDataAcc->GetCheckButtonSize(); |
|
pCheckBox->SetBoxSize(fSize); |
|
uint32_t dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross; |
|
int32_t iCheckMark = m_pDataAcc->GetCheckButtonMark(); |
|
switch (iCheckMark) { |
|
case XFA_ATTRIBUTEENUM_Check: |
|
dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck; |
|
break; |
|
case XFA_ATTRIBUTEENUM_Circle: |
|
dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle; |
|
break; |
|
case XFA_ATTRIBUTEENUM_Cross: |
|
break; |
|
case XFA_ATTRIBUTEENUM_Diamond: |
|
dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond; |
|
break; |
|
case XFA_ATTRIBUTEENUM_Square: |
|
dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare; |
|
break; |
|
case XFA_ATTRIBUTEENUM_Star: |
|
dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar; |
|
break; |
|
default: { |
|
int32_t iShape = m_pDataAcc->GetCheckButtonShape(); |
|
if (iShape == XFA_ATTRIBUTEENUM_Round) { |
|
dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle; |
|
} |
|
} break; |
|
} |
|
if (m_pDataAcc->IsAllowNeutral()) { |
|
dwStyleEx |= FWL_STYLEEXT_CKB_3State; |
|
} |
|
pCheckBox->ModifyStylesEx( |
|
dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State); |
|
} |
|
bool CXFA_FFCheckButton::PerformLayout() { |
|
CXFA_FFWidget::PerformLayout(); |
|
FX_FLOAT fCheckSize = m_pDataAcc->GetCheckButtonSize(); |
|
CXFA_Margin mgWidget = m_pDataAcc->GetMargin(); |
|
CFX_RectF rtWidget = GetRectWithoutRotate(); |
|
if (mgWidget) { |
|
XFA_RectWidthoutMargin(rtWidget, mgWidget); |
|
} |
|
int32_t iCapPlacement = -1; |
|
FX_FLOAT fCapReserve = 0; |
|
CXFA_Caption caption = m_pDataAcc->GetCaption(); |
|
if (caption && caption.GetPresence()) { |
|
m_rtCaption = rtWidget; |
|
iCapPlacement = caption.GetPlacementType(); |
|
fCapReserve = caption.GetReserve(); |
|
if (fCapReserve <= 0) { |
|
if (iCapPlacement == XFA_ATTRIBUTEENUM_Top || |
|
iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) { |
|
fCapReserve = rtWidget.height - fCheckSize; |
|
} else { |
|
fCapReserve = rtWidget.width - fCheckSize; |
|
} |
|
} |
|
} |
|
int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left; |
|
int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top; |
|
if (CXFA_Para para = m_pDataAcc->GetPara()) { |
|
iHorzAlign = para.GetHorizontalAlign(); |
|
iVertAlign = para.GetVerticalAlign(); |
|
} |
|
m_rtUI = rtWidget; |
|
CXFA_Margin mgCap = caption.GetMargin(); |
|
switch (iCapPlacement) { |
|
case XFA_ATTRIBUTEENUM_Left: { |
|
m_rtCaption.width = fCapReserve; |
|
CapLeftRightPlacement(mgCap); |
|
m_rtUI.width -= fCapReserve; |
|
m_rtUI.left += fCapReserve; |
|
} break; |
|
case XFA_ATTRIBUTEENUM_Top: { |
|
m_rtCaption.height = fCapReserve; |
|
XFA_RectWidthoutMargin(m_rtCaption, mgCap); |
|
m_rtUI.height -= fCapReserve; |
|
m_rtUI.top += fCapReserve; |
|
} break; |
|
case XFA_ATTRIBUTEENUM_Right: { |
|
m_rtCaption.left = m_rtCaption.right() - fCapReserve; |
|
m_rtCaption.width = fCapReserve; |
|
CapLeftRightPlacement(mgCap); |
|
m_rtUI.width -= fCapReserve; |
|
} break; |
|
case XFA_ATTRIBUTEENUM_Bottom: { |
|
m_rtCaption.top = m_rtCaption.bottom() - fCapReserve; |
|
m_rtCaption.height = fCapReserve; |
|
XFA_RectWidthoutMargin(m_rtCaption, mgCap); |
|
m_rtUI.height -= fCapReserve; |
|
} break; |
|
case XFA_ATTRIBUTEENUM_Inline: |
|
break; |
|
default: |
|
iHorzAlign = XFA_ATTRIBUTEENUM_Right; |
|
break; |
|
} |
|
if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) { |
|
m_rtUI.left += (m_rtUI.width - fCheckSize) / 2; |
|
} else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) { |
|
m_rtUI.left = m_rtUI.right() - fCheckSize; |
|
} |
|
if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) { |
|
m_rtUI.top += (m_rtUI.height - fCheckSize) / 2; |
|
} else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) { |
|
m_rtUI.top = m_rtUI.bottom() - fCheckSize; |
|
} |
|
m_rtUI.width = fCheckSize; |
|
m_rtUI.height = fCheckSize; |
|
AddUIMargin(iCapPlacement); |
|
m_rtCheckBox = m_rtUI; |
|
CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); |
|
if (borderUI) { |
|
CXFA_Margin margin = borderUI.GetMargin(); |
|
if (margin) { |
|
XFA_RectWidthoutMargin(m_rtUI, margin); |
|
} |
|
} |
|
m_rtUI.Normalize(); |
|
LayoutCaption(); |
|
SetFWLRect(); |
|
if (m_pNormalWidget) { |
|
m_pNormalWidget->Update(); |
|
} |
|
return true; |
|
} |
|
void CXFA_FFCheckButton::CapLeftRightPlacement(CXFA_Margin mgCap) { |
|
XFA_RectWidthoutMargin(m_rtCaption, mgCap); |
|
if (m_rtCaption.height < 0) { |
|
m_rtCaption.top += m_rtCaption.height; |
|
} |
|
if (m_rtCaption.width < 0) { |
|
m_rtCaption.left += m_rtCaption.width; |
|
m_rtCaption.width = -m_rtCaption.width; |
|
} |
|
} |
|
void CXFA_FFCheckButton::AddUIMargin(int32_t iCapPlacement) { |
|
CFX_RectF rtUIMargin = m_pDataAcc->GetUIMargin(); |
|
m_rtUI.top -= rtUIMargin.top / 2 - rtUIMargin.height / 2; |
|
FX_FLOAT fLeftAddRight = rtUIMargin.left + rtUIMargin.width; |
|
FX_FLOAT fTopAddBottom = rtUIMargin.top + rtUIMargin.height; |
|
if (m_rtUI.width < fLeftAddRight) { |
|
if (iCapPlacement == XFA_ATTRIBUTEENUM_Right || |
|
iCapPlacement == XFA_ATTRIBUTEENUM_Left) { |
|
m_rtUI.left -= fLeftAddRight - m_rtUI.width; |
|
} else { |
|
m_rtUI.left -= 2 * (fLeftAddRight - m_rtUI.width); |
|
} |
|
m_rtUI.width += 2 * (fLeftAddRight - m_rtUI.width); |
|
} |
|
if (m_rtUI.height < fTopAddBottom) { |
|
if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) { |
|
m_rtUI.left -= fTopAddBottom - m_rtUI.height; |
|
} |
|
m_rtUI.top -= fTopAddBottom - m_rtUI.height; |
|
m_rtUI.height += 2 * (fTopAddBottom - m_rtUI.height); |
|
} |
|
} |
|
void CXFA_FFCheckButton::RenderWidget(CFX_Graphics* pGS, |
|
CFX_Matrix* pMatrix, |
|
uint32_t dwStatus) { |
|
if (!IsMatchVisibleStatus(dwStatus)) |
|
return; |
|
|
|
CFX_Matrix mtRotate = GetRotateMatrix(); |
|
if (pMatrix) |
|
mtRotate.Concat(*pMatrix); |
|
|
|
CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); |
|
CXFA_Border borderUI = m_pDataAcc->GetUIBorder(); |
|
DrawBorder(pGS, borderUI, m_rtUI, &mtRotate, |
|
m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round |
|
? XFA_DRAWBOX_ForceRound |
|
: 0); |
|
RenderCaption(pGS, &mtRotate); |
|
DrawHighlight(pGS, &mtRotate, dwStatus, |
|
m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round); |
|
CFX_Matrix mt(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top); |
|
mt.Concat(mtRotate); |
|
GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt); |
|
} |
|
bool CXFA_FFCheckButton::OnLButtonUp(uint32_t dwFlags, |
|
const CFX_PointF& point) { |
|
if (!m_pNormalWidget || !IsButtonDown()) |
|
return false; |
|
|
|
SetButtonDown(false); |
|
CFWL_MessageMouse ms(nullptr, m_pNormalWidget); |
|
ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp; |
|
ms.m_dwFlags = dwFlags; |
|
ms.m_pos = FWLToClient(point); |
|
TranslateFWLMessage(&ms); |
|
return true; |
|
} |
|
|
|
XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() { |
|
uint32_t dwState = m_pNormalWidget->GetStates(); |
|
if (dwState & FWL_STATE_CKB_Checked) |
|
return XFA_CHECKSTATE_On; |
|
if (dwState & FWL_STATE_CKB_Neutral) |
|
return XFA_CHECKSTATE_Neutral; |
|
return XFA_CHECKSTATE_Off; |
|
} |
|
|
|
bool CXFA_FFCheckButton::CommitData() { |
|
XFA_CHECKSTATE eCheckState = FWLState2XFAState(); |
|
m_pDataAcc->SetCheckState(eCheckState, true); |
|
return true; |
|
} |
|
|
|
bool CXFA_FFCheckButton::IsDataChanged() { |
|
XFA_CHECKSTATE eCheckState = FWLState2XFAState(); |
|
return m_pDataAcc->GetCheckState() != eCheckState; |
|
} |
|
void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) { |
|
if (eCheckState == XFA_CHECKSTATE_Neutral) { |
|
m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral); |
|
} else { |
|
if (eCheckState == XFA_CHECKSTATE_On) |
|
m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked); |
|
else |
|
m_pNormalWidget->RemoveStates(FWL_STATE_CKB_Checked); |
|
} |
|
} |
|
bool CXFA_FFCheckButton::UpdateFWLData() { |
|
if (!m_pNormalWidget) { |
|
return false; |
|
} |
|
XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState(); |
|
SetFWLCheckState(eState); |
|
m_pNormalWidget->Update(); |
|
return true; |
|
} |
|
|
|
void CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) { |
|
m_pOldDelegate->OnProcessMessage(pMessage); |
|
} |
|
|
|
void CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) { |
|
CXFA_FFField::OnProcessEvent(pEvent); |
|
switch (pEvent->GetType()) { |
|
case CFWL_Event::Type::CheckStateChanged: { |
|
CXFA_EventParam eParam; |
|
eParam.m_eType = XFA_EVENT_Change; |
|
m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw); |
|
CXFA_WidgetAcc* pFFExclGroup = m_pDataAcc->GetExclGroup(); |
|
if (ProcessCommittedData()) { |
|
eParam.m_pTarget = pFFExclGroup; |
|
if (pFFExclGroup) { |
|
m_pDocView->AddValidateWidget(pFFExclGroup); |
|
m_pDocView->AddCalculateWidgetAcc(pFFExclGroup); |
|
pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); |
|
} |
|
eParam.m_pTarget = m_pDataAcc; |
|
m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam); |
|
} else { |
|
SetFWLCheckState(m_pDataAcc->GetCheckState()); |
|
} |
|
if (pFFExclGroup) { |
|
eParam.m_pTarget = pFFExclGroup; |
|
pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam); |
|
} |
|
eParam.m_pTarget = m_pDataAcc; |
|
m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
m_pOldDelegate->OnProcessEvent(pEvent); |
|
} |
|
|
|
void CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics, |
|
const CFX_Matrix* pMatrix) { |
|
m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix); |
|
}
|
|
|