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