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/core/cfwl_message.h"
10 #include "xfa/fwl/core/cfwl_widgetmgr.h"
11 #include "xfa/fwl/core/fwl_noteimp.h"
12 #include "xfa/fwl/lightwidget/cfwl_checkbox.h"
13 #include "xfa/fxfa/app/xfa_ffexclgroup.h"
14 #include "xfa/fxfa/app/xfa_fffield.h"
15 #include "xfa/fxfa/include/xfa_ffapp.h"
16 #include "xfa/fxfa/include/xfa_ffdoc.h"
17 #include "xfa/fxfa/include/xfa_ffdocview.h"
18 #include "xfa/fxfa/include/xfa_ffpageview.h"
19 #include "xfa/fxfa/include/xfa_ffwidget.h"
20
CXFA_FFCheckButton(CXFA_FFPageView * pPageView,CXFA_WidgetAcc * pDataAcc)21 CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_FFPageView* pPageView,
22 CXFA_WidgetAcc* pDataAcc)
23 : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(nullptr) {
24 m_rtCheckBox.Set(0, 0, 0, 0);
25 }
~CXFA_FFCheckButton()26 CXFA_FFCheckButton::~CXFA_FFCheckButton() {}
LoadWidget()27 FX_BOOL CXFA_FFCheckButton::LoadWidget() {
28 CFWL_CheckBox* pCheckBox = CFWL_CheckBox::Create();
29 pCheckBox->Initialize();
30 m_pNormalWidget = pCheckBox;
31 m_pNormalWidget->SetLayoutItem(this);
32 IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
33 CFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
34 pNoteDriver->RegisterEventTarget(pWidget, pWidget);
35 m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
36 if (m_pDataAcc->IsRadioButton()) {
37 pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF);
38 }
39 m_pNormalWidget->LockUpdate();
40 UpdateWidgetProperty();
41 SetFWLCheckState(m_pDataAcc->GetCheckState());
42 m_pNormalWidget->UnlockUpdate();
43 return CXFA_FFField::LoadWidget();
44 }
UpdateWidgetProperty()45 void CXFA_FFCheckButton::UpdateWidgetProperty() {
46 CFWL_CheckBox* pCheckBox = (CFWL_CheckBox*)m_pNormalWidget;
47 if (!m_pNormalWidget) {
48 return;
49 }
50 FX_FLOAT fSize = m_pDataAcc->GetCheckButtonSize();
51 pCheckBox->SetBoxSize(fSize);
52 uint32_t dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross;
53 int32_t iCheckMark = m_pDataAcc->GetCheckButtonMark();
54 switch (iCheckMark) {
55 case XFA_ATTRIBUTEENUM_Check:
56 dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck;
57 break;
58 case XFA_ATTRIBUTEENUM_Circle:
59 dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
60 break;
61 case XFA_ATTRIBUTEENUM_Cross:
62 break;
63 case XFA_ATTRIBUTEENUM_Diamond:
64 dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond;
65 break;
66 case XFA_ATTRIBUTEENUM_Square:
67 dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare;
68 break;
69 case XFA_ATTRIBUTEENUM_Star:
70 dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar;
71 break;
72 default: {
73 int32_t iShape = m_pDataAcc->GetCheckButtonShape();
74 if (iShape == XFA_ATTRIBUTEENUM_Round) {
75 dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
76 }
77 } break;
78 }
79 if (m_pDataAcc->IsAllowNeutral()) {
80 dwStyleEx |= FWL_STYLEEXT_CKB_3State;
81 }
82 pCheckBox->ModifyStylesEx(
83 dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State);
84 }
PerformLayout()85 FX_BOOL CXFA_FFCheckButton::PerformLayout() {
86 CXFA_FFWidget::PerformLayout();
87 FX_FLOAT fCheckSize = m_pDataAcc->GetCheckButtonSize();
88 CXFA_Margin mgWidget = m_pDataAcc->GetMargin();
89 CFX_RectF rtWidget;
90 GetRectWithoutRotate(rtWidget);
91 if (mgWidget) {
92 XFA_RectWidthoutMargin(rtWidget, mgWidget);
93 }
94 int32_t iCapPlacement = -1;
95 FX_FLOAT fCapReserve = 0;
96 CXFA_Caption caption = m_pDataAcc->GetCaption();
97 if (caption && caption.GetPresence()) {
98 m_rtCaption.Set(rtWidget.left, rtWidget.top, rtWidget.width,
99 rtWidget.height);
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;
191 m_pDataAcc->GetUIMargin(rtUIMargin);
192 m_rtUI.top -= rtUIMargin.top / 2 - rtUIMargin.height / 2;
193 FX_FLOAT fLeftAddRight = rtUIMargin.left + rtUIMargin.width;
194 FX_FLOAT fTopAddBottom = rtUIMargin.top + rtUIMargin.height;
195 if (m_rtUI.width < fLeftAddRight) {
196 if (iCapPlacement == XFA_ATTRIBUTEENUM_Right ||
197 iCapPlacement == XFA_ATTRIBUTEENUM_Left) {
198 m_rtUI.left -= fLeftAddRight - m_rtUI.width;
199 } else {
200 m_rtUI.left -= 2 * (fLeftAddRight - m_rtUI.width);
201 }
202 m_rtUI.width += 2 * (fLeftAddRight - m_rtUI.width);
203 }
204 if (m_rtUI.height < fTopAddBottom) {
205 if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) {
206 m_rtUI.left -= fTopAddBottom - m_rtUI.height;
207 }
208 m_rtUI.top -= fTopAddBottom - m_rtUI.height;
209 m_rtUI.height += 2 * (fTopAddBottom - m_rtUI.height);
210 }
211 }
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,uint32_t dwStatus)212 void CXFA_FFCheckButton::RenderWidget(CFX_Graphics* pGS,
213 CFX_Matrix* pMatrix,
214 uint32_t dwStatus) {
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(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)238 FX_BOOL CXFA_FFCheckButton::OnLButtonUp(uint32_t dwFlags,
239 FX_FLOAT fx,
240 FX_FLOAT fy) {
241 if (!m_pNormalWidget || !IsButtonDown())
242 return FALSE;
243
244 SetButtonDown(FALSE);
245 CFWL_MsgMouse ms;
246 ms.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
247 ms.m_dwFlags = dwFlags;
248 ms.m_fx = fx;
249 ms.m_fy = fy;
250 FWLToClient(ms.m_fx, ms.m_fy);
251 ms.m_pDstTarget = m_pNormalWidget->m_pIface;
252 TranslateFWLMessage(&ms);
253 return TRUE;
254 }
255
FWLState2XFAState()256 XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() {
257 uint32_t dwState = m_pNormalWidget->GetStates();
258 if (dwState & FWL_STATE_CKB_Checked)
259 return XFA_CHECKSTATE_On;
260 if (dwState & FWL_STATE_CKB_Neutral)
261 return XFA_CHECKSTATE_Neutral;
262 return XFA_CHECKSTATE_Off;
263 }
264
CommitData()265 FX_BOOL CXFA_FFCheckButton::CommitData() {
266 XFA_CHECKSTATE eCheckState = FWLState2XFAState();
267 m_pDataAcc->SetCheckState(eCheckState, true);
268 return TRUE;
269 }
270
IsDataChanged()271 FX_BOOL CXFA_FFCheckButton::IsDataChanged() {
272 XFA_CHECKSTATE eCheckState = FWLState2XFAState();
273 return m_pDataAcc->GetCheckState() != eCheckState;
274 }
SetFWLCheckState(XFA_CHECKSTATE eCheckState)275 void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) {
276 if (eCheckState == XFA_CHECKSTATE_Neutral) {
277 m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral, TRUE);
278 } else {
279 m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked,
280 eCheckState == XFA_CHECKSTATE_On);
281 }
282 }
UpdateFWLData()283 FX_BOOL CXFA_FFCheckButton::UpdateFWLData() {
284 if (!m_pNormalWidget) {
285 return FALSE;
286 }
287 XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState();
288 SetFWLCheckState(eState);
289 m_pNormalWidget->Update();
290 return TRUE;
291 }
292
OnProcessMessage(CFWL_Message * pMessage)293 void CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) {
294 m_pOldDelegate->OnProcessMessage(pMessage);
295 }
296
OnProcessEvent(CFWL_Event * pEvent)297 void CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) {
298 CXFA_FFField::OnProcessEvent(pEvent);
299 switch (pEvent->GetClassID()) {
300 case CFWL_EventType::CheckStateChanged: {
301 CXFA_EventParam eParam;
302 eParam.m_eType = XFA_EVENT_Change;
303 m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw);
304 CXFA_WidgetAcc* pFFExclGroup = m_pDataAcc->GetExclGroup();
305 if (ProcessCommittedData()) {
306 eParam.m_pTarget = pFFExclGroup;
307 if (pFFExclGroup) {
308 m_pDocView->AddValidateWidget(pFFExclGroup);
309 m_pDocView->AddCalculateWidgetAcc(pFFExclGroup);
310 pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
311 }
312 eParam.m_pTarget = m_pDataAcc;
313 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
314 } else {
315 SetFWLCheckState(m_pDataAcc->GetCheckState());
316 }
317 if (pFFExclGroup) {
318 eParam.m_pTarget = pFFExclGroup;
319 pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
320 }
321 eParam.m_pTarget = m_pDataAcc;
322 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
323 break;
324 }
325 default:
326 break;
327 }
328 m_pOldDelegate->OnProcessEvent(pEvent);
329 }
330
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)331 void CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics,
332 const CFX_Matrix* pMatrix) {
333 m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
334 }
335