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"
CXFA_FFCheckButton(CXFA_FFPageView * pPageView,CXFA_WidgetAcc * pDataAcc)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 }
~CXFA_FFCheckButton()22 CXFA_FFCheckButton::~CXFA_FFCheckButton() {}
LoadWidget()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 }
UpdateWidgetProperty()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 }
PerformLayout()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 }
CapLeftRightPlacement(CXFA_Margin mgCap)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 }
AddUIMargin(int32_t iCapPlacement)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 }
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,FX_DWORD dwStatus,int32_t iRotate)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 }
OnLButtonUp(FX_DWORD dwFlags,FX_FLOAT fx,FX_FLOAT fy)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 }
FWLState2XFAState()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 }
CommitData()268 FX_BOOL CXFA_FFCheckButton::CommitData() {
269 XFA_CHECKSTATE eCheckState = FWLState2XFAState();
270 m_pDataAcc->SetCheckState(eCheckState, TRUE);
271 return TRUE;
272 }
IsDataChanged()273 FX_BOOL CXFA_FFCheckButton::IsDataChanged() {
274 XFA_CHECKSTATE eCheckState = FWLState2XFAState();
275 return m_pDataAcc->GetCheckState() != eCheckState;
276 }
SetFWLCheckState(XFA_CHECKSTATE eCheckState)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 }
UpdateFWLData()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 }
OnProcessMessage(CFWL_Message * pMessage)294 int32_t CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) {
295 return m_pOldDelegate->OnProcessMessage(pMessage);
296 }
OnProcessEvent(CFWL_Event * pEvent)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 }
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)330 FWL_ERR CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics,
331 const CFX_Matrix* pMatrix) {
332 return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
333 }
334