Home | History | Annotate | Download | only in app
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/fxfa/app/xfa_ffcheckbutton.h"
      8 
      9 #include "xfa/fwl/cfwl_checkbox.h"
     10 #include "xfa/fwl/cfwl_messagemouse.h"
     11 #include "xfa/fwl/cfwl_notedriver.h"
     12 #include "xfa/fwl/cfwl_widgetmgr.h"
     13 #include "xfa/fxfa/app/xfa_ffexclgroup.h"
     14 #include "xfa/fxfa/app/xfa_fffield.h"
     15 #include "xfa/fxfa/xfa_ffapp.h"
     16 #include "xfa/fxfa/xfa_ffdoc.h"
     17 #include "xfa/fxfa/xfa_ffdocview.h"
     18 #include "xfa/fxfa/xfa_ffpageview.h"
     19 #include "xfa/fxfa/xfa_ffwidget.h"
     20 
     21 CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_WidgetAcc* pDataAcc)
     22     : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {}
     23 
     24 CXFA_FFCheckButton::~CXFA_FFCheckButton() {}
     25 
     26 bool CXFA_FFCheckButton::LoadWidget() {
     27   CFWL_CheckBox* pCheckBox = new CFWL_CheckBox(GetFWLApp());
     28   m_pNormalWidget = pCheckBox;
     29   m_pNormalWidget->SetLayoutItem(this);
     30 
     31   CFWL_NoteDriver* pNoteDriver =
     32       m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
     33   pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
     34 
     35   m_pOldDelegate = m_pNormalWidget->GetDelegate();
     36   m_pNormalWidget->SetDelegate(this);
     37 
     38   if (m_pDataAcc->IsRadioButton())
     39     pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF);
     40 
     41   m_pNormalWidget->LockUpdate();
     42   UpdateWidgetProperty();
     43   SetFWLCheckState(m_pDataAcc->GetCheckState());
     44   m_pNormalWidget->UnlockUpdate();
     45   return CXFA_FFField::LoadWidget();
     46 }
     47 void CXFA_FFCheckButton::UpdateWidgetProperty() {
     48   CFWL_CheckBox* pCheckBox = (CFWL_CheckBox*)m_pNormalWidget;
     49   if (!m_pNormalWidget) {
     50     return;
     51   }
     52   FX_FLOAT fSize = m_pDataAcc->GetCheckButtonSize();
     53   pCheckBox->SetBoxSize(fSize);
     54   uint32_t dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross;
     55   int32_t iCheckMark = m_pDataAcc->GetCheckButtonMark();
     56   switch (iCheckMark) {
     57     case XFA_ATTRIBUTEENUM_Check:
     58       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck;
     59       break;
     60     case XFA_ATTRIBUTEENUM_Circle:
     61       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
     62       break;
     63     case XFA_ATTRIBUTEENUM_Cross:
     64       break;
     65     case XFA_ATTRIBUTEENUM_Diamond:
     66       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond;
     67       break;
     68     case XFA_ATTRIBUTEENUM_Square:
     69       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare;
     70       break;
     71     case XFA_ATTRIBUTEENUM_Star:
     72       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar;
     73       break;
     74     default: {
     75       int32_t iShape = m_pDataAcc->GetCheckButtonShape();
     76       if (iShape == XFA_ATTRIBUTEENUM_Round) {
     77         dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
     78       }
     79     } break;
     80   }
     81   if (m_pDataAcc->IsAllowNeutral()) {
     82     dwStyleEx |= FWL_STYLEEXT_CKB_3State;
     83   }
     84   pCheckBox->ModifyStylesEx(
     85       dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State);
     86 }
     87 bool CXFA_FFCheckButton::PerformLayout() {
     88   CXFA_FFWidget::PerformLayout();
     89   FX_FLOAT fCheckSize = m_pDataAcc->GetCheckButtonSize();
     90   CXFA_Margin mgWidget = m_pDataAcc->GetMargin();
     91   CFX_RectF rtWidget = GetRectWithoutRotate();
     92   if (mgWidget) {
     93     XFA_RectWidthoutMargin(rtWidget, mgWidget);
     94   }
     95   int32_t iCapPlacement = -1;
     96   FX_FLOAT fCapReserve = 0;
     97   CXFA_Caption caption = m_pDataAcc->GetCaption();
     98   if (caption && caption.GetPresence()) {
     99     m_rtCaption = rtWidget;
    100     iCapPlacement = caption.GetPlacementType();
    101     fCapReserve = caption.GetReserve();
    102     if (fCapReserve <= 0) {
    103       if (iCapPlacement == XFA_ATTRIBUTEENUM_Top ||
    104           iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) {
    105         fCapReserve = rtWidget.height - fCheckSize;
    106       } else {
    107         fCapReserve = rtWidget.width - fCheckSize;
    108       }
    109     }
    110   }
    111   int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left;
    112   int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top;
    113   if (CXFA_Para para = m_pDataAcc->GetPara()) {
    114     iHorzAlign = para.GetHorizontalAlign();
    115     iVertAlign = para.GetVerticalAlign();
    116   }
    117   m_rtUI = rtWidget;
    118   CXFA_Margin mgCap = caption.GetMargin();
    119   switch (iCapPlacement) {
    120     case XFA_ATTRIBUTEENUM_Left: {
    121       m_rtCaption.width = fCapReserve;
    122       CapLeftRightPlacement(mgCap);
    123       m_rtUI.width -= fCapReserve;
    124       m_rtUI.left += fCapReserve;
    125     } break;
    126     case XFA_ATTRIBUTEENUM_Top: {
    127       m_rtCaption.height = fCapReserve;
    128       XFA_RectWidthoutMargin(m_rtCaption, mgCap);
    129       m_rtUI.height -= fCapReserve;
    130       m_rtUI.top += fCapReserve;
    131     } break;
    132     case XFA_ATTRIBUTEENUM_Right: {
    133       m_rtCaption.left = m_rtCaption.right() - fCapReserve;
    134       m_rtCaption.width = fCapReserve;
    135       CapLeftRightPlacement(mgCap);
    136       m_rtUI.width -= fCapReserve;
    137     } break;
    138     case XFA_ATTRIBUTEENUM_Bottom: {
    139       m_rtCaption.top = m_rtCaption.bottom() - fCapReserve;
    140       m_rtCaption.height = fCapReserve;
    141       XFA_RectWidthoutMargin(m_rtCaption, mgCap);
    142       m_rtUI.height -= fCapReserve;
    143     } break;
    144     case XFA_ATTRIBUTEENUM_Inline:
    145       break;
    146     default:
    147       iHorzAlign = XFA_ATTRIBUTEENUM_Right;
    148       break;
    149   }
    150   if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) {
    151     m_rtUI.left += (m_rtUI.width - fCheckSize) / 2;
    152   } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) {
    153     m_rtUI.left = m_rtUI.right() - fCheckSize;
    154   }
    155   if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) {
    156     m_rtUI.top += (m_rtUI.height - fCheckSize) / 2;
    157   } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) {
    158     m_rtUI.top = m_rtUI.bottom() - fCheckSize;
    159   }
    160   m_rtUI.width = fCheckSize;
    161   m_rtUI.height = fCheckSize;
    162   AddUIMargin(iCapPlacement);
    163   m_rtCheckBox = m_rtUI;
    164   CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
    165   if (borderUI) {
    166     CXFA_Margin margin = borderUI.GetMargin();
    167     if (margin) {
    168       XFA_RectWidthoutMargin(m_rtUI, margin);
    169     }
    170   }
    171   m_rtUI.Normalize();
    172   LayoutCaption();
    173   SetFWLRect();
    174   if (m_pNormalWidget) {
    175     m_pNormalWidget->Update();
    176   }
    177   return true;
    178 }
    179 void CXFA_FFCheckButton::CapLeftRightPlacement(CXFA_Margin mgCap) {
    180   XFA_RectWidthoutMargin(m_rtCaption, mgCap);
    181   if (m_rtCaption.height < 0) {
    182     m_rtCaption.top += m_rtCaption.height;
    183   }
    184   if (m_rtCaption.width < 0) {
    185     m_rtCaption.left += m_rtCaption.width;
    186     m_rtCaption.width = -m_rtCaption.width;
    187   }
    188 }
    189 void CXFA_FFCheckButton::AddUIMargin(int32_t iCapPlacement) {
    190   CFX_RectF rtUIMargin = m_pDataAcc->GetUIMargin();
    191   m_rtUI.top -= rtUIMargin.top / 2 - rtUIMargin.height / 2;
    192   FX_FLOAT fLeftAddRight = rtUIMargin.left + rtUIMargin.width;
    193   FX_FLOAT fTopAddBottom = rtUIMargin.top + rtUIMargin.height;
    194   if (m_rtUI.width < fLeftAddRight) {
    195     if (iCapPlacement == XFA_ATTRIBUTEENUM_Right ||
    196         iCapPlacement == XFA_ATTRIBUTEENUM_Left) {
    197       m_rtUI.left -= fLeftAddRight - m_rtUI.width;
    198     } else {
    199       m_rtUI.left -= 2 * (fLeftAddRight - m_rtUI.width);
    200     }
    201     m_rtUI.width += 2 * (fLeftAddRight - m_rtUI.width);
    202   }
    203   if (m_rtUI.height < fTopAddBottom) {
    204     if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) {
    205       m_rtUI.left -= fTopAddBottom - m_rtUI.height;
    206     }
    207     m_rtUI.top -= fTopAddBottom - m_rtUI.height;
    208     m_rtUI.height += 2 * (fTopAddBottom - m_rtUI.height);
    209   }
    210 }
    211 void CXFA_FFCheckButton::RenderWidget(CFX_Graphics* pGS,
    212                                       CFX_Matrix* pMatrix,
    213                                       uint32_t dwStatus) {
    214   if (!IsMatchVisibleStatus(dwStatus))
    215     return;
    216 
    217   CFX_Matrix mtRotate = GetRotateMatrix();
    218   if (pMatrix)
    219     mtRotate.Concat(*pMatrix);
    220 
    221   CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
    222   CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
    223   DrawBorder(pGS, borderUI, m_rtUI, &mtRotate,
    224              m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round
    225                  ? XFA_DRAWBOX_ForceRound
    226                  : 0);
    227   RenderCaption(pGS, &mtRotate);
    228   DrawHighlight(pGS, &mtRotate, dwStatus,
    229                 m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round);
    230   CFX_Matrix mt(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top);
    231   mt.Concat(mtRotate);
    232   GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt);
    233 }
    234 bool CXFA_FFCheckButton::OnLButtonUp(uint32_t dwFlags,
    235                                      const CFX_PointF& point) {
    236   if (!m_pNormalWidget || !IsButtonDown())
    237     return false;
    238 
    239   SetButtonDown(false);
    240   CFWL_MessageMouse ms(nullptr, m_pNormalWidget);
    241   ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
    242   ms.m_dwFlags = dwFlags;
    243   ms.m_pos = FWLToClient(point);
    244   TranslateFWLMessage(&ms);
    245   return true;
    246 }
    247 
    248 XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() {
    249   uint32_t dwState = m_pNormalWidget->GetStates();
    250   if (dwState & FWL_STATE_CKB_Checked)
    251     return XFA_CHECKSTATE_On;
    252   if (dwState & FWL_STATE_CKB_Neutral)
    253     return XFA_CHECKSTATE_Neutral;
    254   return XFA_CHECKSTATE_Off;
    255 }
    256 
    257 bool CXFA_FFCheckButton::CommitData() {
    258   XFA_CHECKSTATE eCheckState = FWLState2XFAState();
    259   m_pDataAcc->SetCheckState(eCheckState, true);
    260   return true;
    261 }
    262 
    263 bool CXFA_FFCheckButton::IsDataChanged() {
    264   XFA_CHECKSTATE eCheckState = FWLState2XFAState();
    265   return m_pDataAcc->GetCheckState() != eCheckState;
    266 }
    267 void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) {
    268   if (eCheckState == XFA_CHECKSTATE_Neutral) {
    269     m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral);
    270   } else {
    271     if (eCheckState == XFA_CHECKSTATE_On)
    272       m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked);
    273     else
    274       m_pNormalWidget->RemoveStates(FWL_STATE_CKB_Checked);
    275   }
    276 }
    277 bool CXFA_FFCheckButton::UpdateFWLData() {
    278   if (!m_pNormalWidget) {
    279     return false;
    280   }
    281   XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState();
    282   SetFWLCheckState(eState);
    283   m_pNormalWidget->Update();
    284   return true;
    285 }
    286 
    287 void CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) {
    288   m_pOldDelegate->OnProcessMessage(pMessage);
    289 }
    290 
    291 void CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) {
    292   CXFA_FFField::OnProcessEvent(pEvent);
    293   switch (pEvent->GetType()) {
    294     case CFWL_Event::Type::CheckStateChanged: {
    295       CXFA_EventParam eParam;
    296       eParam.m_eType = XFA_EVENT_Change;
    297       m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw);
    298       CXFA_WidgetAcc* pFFExclGroup = m_pDataAcc->GetExclGroup();
    299       if (ProcessCommittedData()) {
    300         eParam.m_pTarget = pFFExclGroup;
    301         if (pFFExclGroup) {
    302           m_pDocView->AddValidateWidget(pFFExclGroup);
    303           m_pDocView->AddCalculateWidgetAcc(pFFExclGroup);
    304           pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
    305         }
    306         eParam.m_pTarget = m_pDataAcc;
    307         m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
    308       } else {
    309         SetFWLCheckState(m_pDataAcc->GetCheckState());
    310       }
    311       if (pFFExclGroup) {
    312         eParam.m_pTarget = pFFExclGroup;
    313         pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
    314       }
    315       eParam.m_pTarget = m_pDataAcc;
    316       m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
    317       break;
    318     }
    319     default:
    320       break;
    321   }
    322   m_pOldDelegate->OnProcessEvent(pEvent);
    323 }
    324 
    325 void CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics,
    326                                       const CFX_Matrix* pMatrix) {
    327   m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
    328 }
    329