• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CXFA_FFCheckButton(CXFA_WidgetAcc * pDataAcc)21 CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_WidgetAcc* pDataAcc)
22     : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {}
23 
~CXFA_FFCheckButton()24 CXFA_FFCheckButton::~CXFA_FFCheckButton() {}
25 
LoadWidget()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 }
UpdateWidgetProperty()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 }
PerformLayout()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 }
CapLeftRightPlacement(CXFA_Margin mgCap)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 }
AddUIMargin(int32_t iCapPlacement)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 }
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,uint32_t dwStatus)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 }
OnLButtonUp(uint32_t dwFlags,const CFX_PointF & point)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 
FWLState2XFAState()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 
CommitData()257 bool CXFA_FFCheckButton::CommitData() {
258   XFA_CHECKSTATE eCheckState = FWLState2XFAState();
259   m_pDataAcc->SetCheckState(eCheckState, true);
260   return true;
261 }
262 
IsDataChanged()263 bool CXFA_FFCheckButton::IsDataChanged() {
264   XFA_CHECKSTATE eCheckState = FWLState2XFAState();
265   return m_pDataAcc->GetCheckState() != eCheckState;
266 }
SetFWLCheckState(XFA_CHECKSTATE eCheckState)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 }
UpdateFWLData()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 
OnProcessMessage(CFWL_Message * pMessage)287 void CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) {
288   m_pOldDelegate->OnProcessMessage(pMessage);
289 }
290 
OnProcessEvent(CFWL_Event * pEvent)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 
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)325 void CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics,
326                                       const CFX_Matrix* pMatrix) {
327   m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
328 }
329