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/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_common.h"
      9 #include "xfa_ffwidget.h"
     10 #include "xfa_fffield.h"
     11 #include "xfa_ffpageview.h"
     12 #include "xfa_ffcheckbutton.h"
     13 #include "xfa_ffexclgroup.h"
     14 #include "xfa_ffdocview.h"
     15 #include "xfa_ffapp.h"
     16 #include "xfa_ffdoc.h"
     17 CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_FFPageView* pPageView,
     18                                        CXFA_WidgetAcc* pDataAcc)
     19     : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(NULL) {
     20   m_rtCheckBox.Set(0, 0, 0, 0);
     21 }
     22 CXFA_FFCheckButton::~CXFA_FFCheckButton() {}
     23 FX_BOOL CXFA_FFCheckButton::LoadWidget() {
     24   CFWL_CheckBox* pCheckBox = CFWL_CheckBox::Create();
     25   pCheckBox->Initialize();
     26   m_pNormalWidget = pCheckBox;
     27   IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
     28   m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
     29   IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
     30   pNoteDriver->RegisterEventTarget(pWidget, pWidget);
     31   m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
     32   if (m_pDataAcc->IsRadioButton()) {
     33     pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF);
     34   }
     35   m_pNormalWidget = (CFWL_Widget*)pCheckBox;
     36   m_pNormalWidget->SetPrivateData(m_pNormalWidget->GetWidget(), this, NULL);
     37   m_pNormalWidget->LockUpdate();
     38   UpdateWidgetProperty();
     39   XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState();
     40   SetFWLCheckState(eState);
     41   m_pNormalWidget->UnlockUpdate();
     42   return CXFA_FFField::LoadWidget();
     43 }
     44 void CXFA_FFCheckButton::UpdateWidgetProperty() {
     45   CFWL_CheckBox* pCheckBox = (CFWL_CheckBox*)m_pNormalWidget;
     46   if (!m_pNormalWidget) {
     47     return;
     48   }
     49   FX_FLOAT fSize = m_pDataAcc->GetCheckButtonSize();
     50   pCheckBox->SetBoxSize(fSize);
     51   FX_DWORD dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross;
     52   int32_t iCheckMark = m_pDataAcc->GetCheckButtonMark();
     53   switch (iCheckMark) {
     54     case XFA_ATTRIBUTEENUM_Check:
     55       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck;
     56       break;
     57     case XFA_ATTRIBUTEENUM_Circle:
     58       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
     59       break;
     60     case XFA_ATTRIBUTEENUM_Cross:
     61       break;
     62     case XFA_ATTRIBUTEENUM_Diamond:
     63       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond;
     64       break;
     65     case XFA_ATTRIBUTEENUM_Square:
     66       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare;
     67       break;
     68     case XFA_ATTRIBUTEENUM_Star:
     69       dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar;
     70       break;
     71     default: {
     72       int32_t iShape = m_pDataAcc->GetCheckButtonShape();
     73       if (iShape == XFA_ATTRIBUTEENUM_Round) {
     74         dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
     75       }
     76     } break;
     77   }
     78   if (m_pDataAcc->IsAllowNeutral()) {
     79     dwStyleEx |= FWL_STYLEEXT_CKB_3State;
     80   }
     81   pCheckBox->ModifyStylesEx(
     82       dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State);
     83 }
     84 FX_BOOL CXFA_FFCheckButton::PerformLayout() {
     85   CXFA_FFWidget::PerformLayout();
     86   FX_FLOAT fCheckSize = m_pDataAcc->GetCheckButtonSize();
     87   CXFA_Margin mgWidget = m_pDataAcc->GetMargin();
     88   CFX_RectF rtWidget;
     89   GetRectWithoutRotate(rtWidget);
     90   if (mgWidget.IsExistInXML()) {
     91     XFA_RectWidthoutMargin(rtWidget, mgWidget);
     92   }
     93   int32_t iCapPlacement = -1;
     94   FX_FLOAT fCapReserve = 0;
     95   CXFA_Caption caption = m_pDataAcc->GetCaption();
     96   if (caption.IsExistInXML() && caption.GetPresence()) {
     97     m_rtCaption.Set(rtWidget.left, rtWidget.top, rtWidget.width,
     98                     rtWidget.height);
     99     iCapPlacement = caption.GetPlacementType();
    100     fCapReserve = caption.GetReserve();
    101     if (fCapReserve <= 0) {
    102       if (iCapPlacement == XFA_ATTRIBUTEENUM_Top ||
    103           iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) {
    104         fCapReserve = rtWidget.height - fCheckSize;
    105       } else {
    106         fCapReserve = rtWidget.width - fCheckSize;
    107       }
    108     }
    109   }
    110   int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left;
    111   int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top;
    112   if (CXFA_Para para = m_pDataAcc->GetPara()) {
    113     iHorzAlign = para.GetHorizontalAlign();
    114     iVertAlign = para.GetVerticalAlign();
    115   }
    116   m_rtUI = rtWidget;
    117   CXFA_Margin mgCap = caption.GetMargin();
    118   switch (iCapPlacement) {
    119     case XFA_ATTRIBUTEENUM_Left: {
    120       m_rtCaption.width = fCapReserve;
    121       CapLeftRightPlacement(mgCap);
    122       m_rtUI.width -= fCapReserve;
    123       m_rtUI.left += fCapReserve;
    124     } break;
    125     case XFA_ATTRIBUTEENUM_Top: {
    126       m_rtCaption.height = fCapReserve;
    127       XFA_RectWidthoutMargin(m_rtCaption, mgCap);
    128       m_rtUI.height -= fCapReserve;
    129       m_rtUI.top += fCapReserve;
    130     } break;
    131     case XFA_ATTRIBUTEENUM_Right: {
    132       m_rtCaption.left = m_rtCaption.right() - fCapReserve;
    133       m_rtCaption.width = fCapReserve;
    134       CapLeftRightPlacement(mgCap);
    135       m_rtUI.width -= fCapReserve;
    136     } break;
    137     case XFA_ATTRIBUTEENUM_Bottom: {
    138       m_rtCaption.top = m_rtCaption.bottom() - fCapReserve;
    139       m_rtCaption.height = fCapReserve;
    140       XFA_RectWidthoutMargin(m_rtCaption, mgCap);
    141       m_rtUI.height -= fCapReserve;
    142     } break;
    143     case XFA_ATTRIBUTEENUM_Inline:
    144       break;
    145     default:
    146       iHorzAlign = XFA_ATTRIBUTEENUM_Right;
    147       break;
    148   }
    149   if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) {
    150     m_rtUI.left += (m_rtUI.width - fCheckSize) / 2;
    151   } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) {
    152     m_rtUI.left = m_rtUI.right() - fCheckSize;
    153   }
    154   if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) {
    155     m_rtUI.top += (m_rtUI.height - fCheckSize) / 2;
    156   } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) {
    157     m_rtUI.top = m_rtUI.bottom() - fCheckSize;
    158   }
    159   m_rtUI.width = fCheckSize;
    160   m_rtUI.height = fCheckSize;
    161   AddUIMargin(iCapPlacement);
    162   m_rtCheckBox = m_rtUI;
    163   CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
    164   if (borderUI) {
    165     CXFA_Margin margin = borderUI.GetMargin();
    166     if (margin.IsExistInXML()) {
    167       XFA_RectWidthoutMargin(m_rtUI, margin);
    168     }
    169   }
    170   m_rtUI.Normalize();
    171   LayoutCaption();
    172   SetFWLRect();
    173   if (m_pNormalWidget) {
    174     m_pNormalWidget->Update();
    175   }
    176   return TRUE;
    177 }
    178 void CXFA_FFCheckButton::CapLeftRightPlacement(CXFA_Margin mgCap) {
    179   XFA_RectWidthoutMargin(m_rtCaption, mgCap);
    180   if (m_rtCaption.height < 0) {
    181     m_rtCaption.top += m_rtCaption.height;
    182   }
    183   if (m_rtCaption.width < 0) {
    184     m_rtCaption.left += m_rtCaption.width;
    185     m_rtCaption.width = -m_rtCaption.width;
    186   }
    187 }
    188 void CXFA_FFCheckButton::AddUIMargin(int32_t iCapPlacement) {
    189   CFX_RectF rtUIMargin;
    190   m_pDataAcc->GetUIMargin(rtUIMargin);
    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                                       FX_DWORD dwStatus,
    214                                       int32_t iRotate) {
    215   if (!IsMatchVisibleStatus(dwStatus)) {
    216     return;
    217   }
    218   CFX_Matrix mtRotate;
    219   GetRotateMatrix(mtRotate);
    220   if (pMatrix) {
    221     mtRotate.Concat(*pMatrix);
    222   }
    223   CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
    224   CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
    225   DrawBorder(pGS, borderUI, m_rtUI, &mtRotate,
    226              m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round
    227                  ? XFA_DRAWBOX_ForceRound
    228                  : 0);
    229   RenderCaption(pGS, &mtRotate);
    230   DrawHighlight(pGS, &mtRotate, dwStatus,
    231                 m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round);
    232   CFX_Matrix mt;
    233   mt.Set(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top);
    234   mt.Concat(mtRotate);
    235   GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
    236                                                  pGS, &mt);
    237 }
    238 FX_BOOL CXFA_FFCheckButton::OnLButtonUp(FX_DWORD dwFlags,
    239                                         FX_FLOAT fx,
    240                                         FX_FLOAT fy) {
    241   if (!m_pNormalWidget) {
    242     return FALSE;
    243   }
    244   if (!IsButtonDown()) {
    245     return FALSE;
    246   }
    247   SetButtonDown(FALSE);
    248   CFWL_MsgMouse ms;
    249   ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonUp;
    250   ms.m_dwFlags = dwFlags;
    251   ms.m_fx = fx;
    252   ms.m_fy = fy;
    253   FWLToClient(ms.m_fx, ms.m_fy);
    254   ms.m_pDstTarget = m_pNormalWidget->m_pIface;
    255   TranslateFWLMessage(&ms);
    256   return TRUE;
    257 }
    258 XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() {
    259   XFA_CHECKSTATE eCheckState = XFA_CHECKSTATE_Off;
    260   FX_DWORD dwState = m_pNormalWidget->GetStates();
    261   if (dwState & FWL_STATE_CKB_Checked) {
    262     eCheckState = XFA_CHECKSTATE_On;
    263   } else if (dwState & FWL_STATE_CKB_Neutral) {
    264     eCheckState = XFA_CHECKSTATE_Neutral;
    265   }
    266   return eCheckState;
    267 }
    268 FX_BOOL CXFA_FFCheckButton::CommitData() {
    269   XFA_CHECKSTATE eCheckState = FWLState2XFAState();
    270   m_pDataAcc->SetCheckState(eCheckState, TRUE);
    271   return TRUE;
    272 }
    273 FX_BOOL CXFA_FFCheckButton::IsDataChanged() {
    274   XFA_CHECKSTATE eCheckState = FWLState2XFAState();
    275   return m_pDataAcc->GetCheckState() != eCheckState;
    276 }
    277 void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) {
    278   if (eCheckState == XFA_CHECKSTATE_Neutral) {
    279     m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral, TRUE);
    280   } else {
    281     m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked,
    282                                eCheckState == XFA_CHECKSTATE_On);
    283   }
    284 }
    285 FX_BOOL CXFA_FFCheckButton::UpdateFWLData() {
    286   if (!m_pNormalWidget) {
    287     return FALSE;
    288   }
    289   XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState();
    290   SetFWLCheckState(eState);
    291   m_pNormalWidget->Update();
    292   return TRUE;
    293 }
    294 int32_t CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) {
    295   return m_pOldDelegate->OnProcessMessage(pMessage);
    296 }
    297 FWL_ERR CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) {
    298   CXFA_FFField::OnProcessEvent(pEvent);
    299   FX_DWORD dwEventID = pEvent->GetClassID();
    300   switch (dwEventID) {
    301     case FWL_EVTHASH_CKB_CheckStateChanged: {
    302       CXFA_EventParam eParam;
    303       eParam.m_eType = XFA_EVENT_Change;
    304       m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw);
    305       CXFA_WidgetAcc* pFFExclGroup = m_pDataAcc->GetExclGroup();
    306       if (ProcessCommittedData()) {
    307         eParam.m_pTarget = pFFExclGroup;
    308         if (pFFExclGroup) {
    309           m_pDocView->AddValidateWidget(pFFExclGroup);
    310           m_pDocView->AddCalculateWidgetAcc(pFFExclGroup);
    311           pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
    312         }
    313         eParam.m_pTarget = m_pDataAcc;
    314         m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
    315       } else {
    316         SetFWLCheckState(m_pDataAcc->GetCheckState());
    317       }
    318       if (pFFExclGroup) {
    319         eParam.m_pTarget = pFFExclGroup;
    320         pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
    321       }
    322       eParam.m_pTarget = m_pDataAcc;
    323       m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
    324       break;
    325     }
    326     default: {}
    327   }
    328   return m_pOldDelegate->OnProcessEvent(pEvent);
    329 }
    330 FWL_ERR CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics,
    331                                          const CFX_Matrix* pMatrix) {
    332   return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
    333 }
    334