Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fwl / src / basewidget / fwl_checkboximp.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 "../core/include/fwl_targetimp.h"\r
9 #include "../core/include/fwl_noteimp.h"\r
10 #include "../core/include/fwl_widgetimp.h"\r
11 #include "../core/include/fwl_widgetmgrimp.h"\r
12 #include "include/fwl_checkboximp.h"\r
13 #define FWL_CKB_CaptionMargin   5\r
14 IFWL_CheckBox* IFWL_CheckBox::Create()\r
15 {\r
16     return new IFWL_CheckBox;\r
17 }\r
18 IFWL_CheckBox::IFWL_CheckBox()\r
19 {\r
20     m_pData = NULL;\r
21 }\r
22 IFWL_CheckBox::~IFWL_CheckBox()\r
23 {\r
24     if (m_pData) {\r
25         delete (CFWL_CheckBoxImp*)m_pData;\r
26         m_pData = NULL;\r
27     }\r
28 }\r
29 FWL_ERR IFWL_CheckBox::Initialize(IFWL_Widget *pOuter)\r
30 {\r
31     m_pData = FX_NEW CFWL_CheckBoxImp(pOuter);\r
32     ((CFWL_CheckBoxImp*)m_pData)->SetInterface(this);\r
33     return ((CFWL_CheckBoxImp*)m_pData)->Initialize();\r
34 }\r
35 FWL_ERR IFWL_CheckBox::Initialize(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter)\r
36 {\r
37     m_pData = FX_NEW CFWL_CheckBoxImp(properties, pOuter);\r
38     ((CFWL_CheckBoxImp*)m_pData)->SetInterface(this);\r
39     return ((CFWL_CheckBoxImp*)m_pData)->Initialize();\r
40 }\r
41 FX_INT32 IFWL_CheckBox::GetCheckState()\r
42 {\r
43     return ((CFWL_CheckBoxImp*)m_pData)->GetCheckState();\r
44 }\r
45 FWL_ERR IFWL_CheckBox::SetCheckState(FX_INT32 iCheck)\r
46 {\r
47     return ((CFWL_CheckBoxImp*)m_pData)->SetCheckState(iCheck);\r
48 }\r
49 IFWL_RadioButton* IFWL_RadioButton::Create()\r
50 {\r
51     return new IFWL_RadioButton;\r
52 }\r
53 IFWL_RadioButton::IFWL_RadioButton()\r
54 {\r
55     m_pData = NULL;\r
56 }\r
57 IFWL_RadioButton::~IFWL_RadioButton()\r
58 {\r
59     if (m_pData) {\r
60         delete (CFWL_CheckBoxImp*)m_pData;\r
61         m_pData = NULL;\r
62     }\r
63 }\r
64 FWL_ERR IFWL_RadioButton::Initialize(IFWL_Widget *pOuter)\r
65 {\r
66     m_pData = FX_NEW CFWL_CheckBoxImp(pOuter);\r
67     ((CFWL_CheckBoxImp*)m_pData)->SetInterface(this);\r
68     return ((CFWL_CheckBoxImp*)m_pData)->Initialize();\r
69 }\r
70 FWL_ERR IFWL_RadioButton::Initialize(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter)\r
71 {\r
72     m_pData = FX_NEW CFWL_CheckBoxImp(properties, pOuter);\r
73     ((CFWL_CheckBoxImp*)m_pData)->SetInterface(this);\r
74     return ((CFWL_CheckBoxImp*)m_pData)->Initialize();\r
75 }\r
76 CFWL_CheckBoxImp::CFWL_CheckBoxImp(IFWL_Widget *pOuter )\r
77     : CFWL_WidgetImp(pOuter)\r
78     , m_dwTTOStyles(FDE_TTOSTYLE_SingleLine)\r
79     , m_iTTOAlign(FDE_TTOALIGNMENT_Center)\r
80     , m_bBtnDown(FALSE)\r
81 {\r
82     m_rtClient.Reset();\r
83     m_rtBox.Reset();\r
84     m_rtCaption.Reset();\r
85     m_rtFocus.Reset();\r
86 }\r
87 CFWL_CheckBoxImp::CFWL_CheckBoxImp(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter )\r
88     : CFWL_WidgetImp(properties, pOuter)\r
89     , m_dwTTOStyles(FDE_TTOSTYLE_SingleLine)\r
90     , m_iTTOAlign(FDE_TTOALIGNMENT_Center)\r
91     , m_bBtnDown(FALSE)\r
92 {\r
93     m_rtClient.Reset();\r
94     m_rtBox.Reset();\r
95     m_rtCaption.Reset();\r
96     m_rtFocus.Reset();\r
97 }\r
98 CFWL_CheckBoxImp::~CFWL_CheckBoxImp()\r
99 {\r
100 }\r
101 FWL_ERR CFWL_CheckBoxImp::GetClassName(CFX_WideString &wsClass) const\r
102 {\r
103     wsClass = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_RadioButton) ? FWL_CLASS_RadioButton : FWL_CLASS_CheckBox;\r
104     return FWL_ERR_Succeeded;\r
105 }\r
106 FX_DWORD CFWL_CheckBoxImp::GetClassID() const\r
107 {\r
108     return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_RadioButton ? FWL_CLASSHASH_RadioButton : FWL_CLASSHASH_CheckBox;\r
109 }\r
110 FWL_ERR CFWL_CheckBoxImp::Initialize()\r
111 {\r
112     _FWL_ERR_CHECK_RETURN_VALUE_IF_FAIL(CFWL_WidgetImp::Initialize(), FWL_ERR_Indefinite);\r
113     m_pDelegate = (IFWL_WidgetDelegate*) FX_NEW CFWL_CheckBoxImpDelegate(this);\r
114     return FWL_ERR_Succeeded;\r
115 }\r
116 FWL_ERR CFWL_CheckBoxImp::Finalize()\r
117 {\r
118     if ( m_pDelegate) {\r
119         delete (CFWL_CheckBoxImpDelegate*)m_pDelegate;\r
120         m_pDelegate = NULL;\r
121     }\r
122     return CFWL_WidgetImp::Finalize();\r
123 }\r
124 FWL_ERR CFWL_CheckBoxImp::GetWidgetRect(CFX_RectF &rect, FX_BOOL bAutoSize )\r
125 {\r
126     if (bAutoSize) {\r
127         rect.Set(0, 0, 0, 0);\r
128         if (!m_pProperties->m_pThemeProvider) {\r
129             m_pProperties->m_pThemeProvider = GetAvailableTheme();\r
130         }\r
131         _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pThemeProvider, FWL_ERR_Indefinite);\r
132         _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pDataProvider, FWL_ERR_Indefinite);\r
133         CFX_WideString wsCaption;\r
134         m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption);\r
135         if (wsCaption.GetLength() > 0) {\r
136             CFX_SizeF sz = CalcTextSize(wsCaption,\r
137                                         m_pProperties->m_pThemeProvider,\r
138                                         m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine);\r
139             rect.Set(0, 0, sz.x, sz.y);\r
140         }\r
141         rect.Inflate(FWL_CKB_CaptionMargin, FWL_CKB_CaptionMargin);\r
142         IFWL_CheckBoxDP *pData = (IFWL_CheckBoxDP*)m_pProperties->m_pDataProvider;\r
143         FX_FLOAT fCheckBox = pData->GetBoxSize(m_pInterface);\r
144         rect.width += fCheckBox;\r
145         if (rect.height < fCheckBox) {\r
146             rect.height = fCheckBox;\r
147         }\r
148         CFWL_WidgetImp::GetWidgetRect(rect, TRUE);\r
149     } else {\r
150         rect = m_pProperties->m_rtWidget;\r
151     }\r
152     return FWL_ERR_Succeeded;\r
153 }\r
154 FWL_ERR CFWL_CheckBoxImp::Update()\r
155 {\r
156     if (IsLocked()) {\r
157         return FWL_ERR_Indefinite;\r
158     }\r
159     if (!m_pProperties->m_pThemeProvider) {\r
160         m_pProperties->m_pThemeProvider = GetAvailableTheme();\r
161     }\r
162     UpdateTextOutStyles();\r
163     Layout();\r
164     return FWL_ERR_Succeeded;\r
165 }\r
166 FWL_ERR CFWL_CheckBoxImp::DrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix )\r
167 {\r
168     _FWL_RETURN_VALUE_IF_FAIL(pGraphics, FWL_ERR_Indefinite);\r
169     _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pThemeProvider, FWL_ERR_Indefinite);\r
170     IFWL_ThemeProvider *pTheme = m_pProperties->m_pThemeProvider;\r
171     if (HasBorder()) {\r
172         DrawBorder(pGraphics, FWL_PART_CKB_Border, m_pProperties->m_pThemeProvider, pMatrix);\r
173     }\r
174     if (HasEdge()) {\r
175         DrawEdge(pGraphics, FWL_PART_CKB_Edge, pTheme, pMatrix);\r
176     }\r
177     FX_INT32 dwStates = GetPartStates();\r
178     {\r
179         CFWL_ThemeBackground param;\r
180         param.m_pWidget = m_pInterface;\r
181         param.m_iPart = FWL_PART_CKB_Background;\r
182         param.m_dwStates = dwStates;\r
183         param.m_pGraphics = pGraphics;\r
184         if (pMatrix) {\r
185             param.m_matrix.Concat(*pMatrix);\r
186         }\r
187         param.m_rtPart = m_rtClient;\r
188         if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {\r
189             param.m_pData = &m_rtFocus;\r
190         }\r
191         pTheme->DrawBackground(&param);\r
192         param.m_iPart = FWL_PART_CKB_CheckBox;\r
193         param.m_rtPart = m_rtBox;\r
194         pTheme->DrawBackground(&param);\r
195     }\r
196     _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pDataProvider, FWL_ERR_Indefinite);\r
197     {\r
198         CFX_WideString wsCaption;\r
199         m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption);\r
200         FX_INT32 iLen = wsCaption.GetLength();\r
201         _FWL_RETURN_VALUE_IF_FAIL(iLen > 0, FWL_ERR_Indefinite);\r
202         CFWL_ThemeText textParam;\r
203         textParam.m_pWidget = m_pInterface;\r
204         textParam.m_iPart = FWL_PART_CKB_Caption;\r
205         textParam.m_dwStates = dwStates;\r
206         textParam.m_pGraphics = pGraphics;\r
207         if(pMatrix) {\r
208             textParam.m_matrix.Concat(*pMatrix);\r
209         }\r
210         textParam.m_rtPart = m_rtCaption;\r
211         textParam.m_wsText = wsCaption;\r
212         textParam.m_dwTTOStyles = m_dwTTOStyles;\r
213         textParam.m_iTTOAlign = m_iTTOAlign;\r
214         pTheme->DrawText(&textParam);\r
215     }\r
216     return FWL_ERR_Succeeded;\r
217 }\r
218 FX_INT32 CFWL_CheckBoxImp::GetCheckState()\r
219 {\r
220     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)\r
221             && ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Neutral)) {\r
222         return 2;\r
223     }\r
224     if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Checked) {\r
225         return 1;\r
226     }\r
227     return 0;\r
228 }\r
229 FWL_ERR CFWL_CheckBoxImp::SetCheckState(FX_INT32 iCheck)\r
230 {\r
231     m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;\r
232     switch(iCheck) {\r
233         case 0: {\r
234                 break;\r
235             }\r
236         case 1: {\r
237                 m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;\r
238                 break;\r
239             }\r
240         case 2: {\r
241                 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) {\r
242                     m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral;\r
243                 }\r
244                 break;\r
245             }\r
246         default: {\r
247             }\r
248     }\r
249     Repaint(&m_rtClient);\r
250     return FWL_ERR_Succeeded;\r
251 }\r
252 void CFWL_CheckBoxImp::Layout()\r
253 {\r
254     FX_INT32 width = FX_INT32(m_pProperties->m_rtWidget.width + 0.5f);\r
255     FX_INT32 height = FX_INT32(m_pProperties->m_rtWidget.height + 0.5f);\r
256     m_pProperties->m_rtWidget.width = (FX_FLOAT)width;\r
257     m_pProperties->m_rtWidget.height = (FX_FLOAT)height;\r
258     GetClientRect(m_rtClient);\r
259     FX_FLOAT fBoxTop = m_rtClient.top;\r
260     FX_FLOAT fBoxLeft = m_rtClient.left;\r
261     FX_FLOAT fTextLeft = 0.0, fTextRight = 0.0;\r
262     FX_FLOAT fClientRight = m_rtClient.right();\r
263     FX_FLOAT fClientBottom = m_rtClient.bottom();\r
264     _FWL_RETURN_IF_FAIL(m_pProperties->m_pDataProvider);\r
265     IFWL_CheckBoxDP *pData = (IFWL_CheckBoxDP*)m_pProperties->m_pDataProvider;\r
266     FX_FLOAT fCheckBox = pData->GetBoxSize(m_pInterface);\r
267     switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) {\r
268         case FWL_STYLEEXT_CKB_Top: {\r
269                 fBoxTop = m_rtClient.top;\r
270                 break;\r
271             }\r
272         case FWL_STYLEEXT_CKB_Bottom: {\r
273                 fBoxTop = fClientBottom - fCheckBox;\r
274                 break;\r
275             }\r
276         case FWL_STYLEEXT_CKB_VCenter:\r
277         default: {\r
278                 fBoxTop = m_rtClient.top + (m_rtClient.height - fCheckBox) / 2;\r
279                 fBoxTop = FXSYS_floor(fBoxTop);\r
280             }\r
281     }\r
282     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_LeftText) {\r
283         fBoxLeft = fClientRight - fCheckBox;\r
284         fTextLeft = m_rtClient.left;\r
285         fTextRight = fBoxLeft;\r
286     } else {\r
287         fTextLeft = fBoxLeft + fCheckBox;\r
288         fTextRight = fClientRight;\r
289     }\r
290     m_rtBox.Set(fBoxLeft, fBoxTop, fCheckBox, fCheckBox);\r
291     m_rtCaption.Set(fTextLeft, m_rtClient.top, fTextRight - fTextLeft, m_rtClient.height);\r
292     m_rtCaption.Inflate(-FWL_CKB_CaptionMargin, -FWL_CKB_CaptionMargin);\r
293     CFX_RectF rtFocus;\r
294     rtFocus.Set(m_rtCaption.left, m_rtCaption.top, m_rtCaption.width, m_rtCaption.height);\r
295     CFX_WideString wsCaption;\r
296     m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption);\r
297     if (wsCaption.IsEmpty()) {\r
298         m_rtFocus.Set(0, 0, 0, 0);\r
299     } else {\r
300         CalcTextRect(wsCaption, m_pProperties->m_pThemeProvider, m_dwTTOStyles, m_iTTOAlign, rtFocus);\r
301         if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine) == 0) {\r
302             FX_FLOAT fWidth = FX_MAX(m_rtCaption.width, rtFocus.width);\r
303             FX_FLOAT fHeight = FX_MIN(m_rtCaption.height, rtFocus.height);\r
304             FX_FLOAT fLeft = m_rtCaption.left;\r
305             FX_FLOAT fTop = m_rtCaption.top;\r
306             if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) == FWL_STYLEEXT_CKB_Center) {\r
307                 fLeft = m_rtCaption.left + (m_rtCaption.width - fWidth) / 2;\r
308             } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) == FWL_STYLEEXT_CKB_Right) {\r
309                 fLeft = m_rtCaption.right() - fWidth;\r
310             }\r
311             if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) == FWL_STYLEEXT_CKB_VCenter) {\r
312                 fTop = m_rtCaption.top + (m_rtCaption.height - fHeight) / 2;\r
313             } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) == FWL_STYLEEXT_CKB_Bottom) {\r
314                 fTop = m_rtCaption.bottom() - fHeight;\r
315             }\r
316             m_rtFocus.Set(fLeft, fTop, fWidth, fHeight);\r
317         } else {\r
318             m_rtFocus.Set(rtFocus.left, rtFocus.top, rtFocus.width, rtFocus.height);\r
319         }\r
320         m_rtFocus.Inflate(1, 1);\r
321     }\r
322 }\r
323 FX_DWORD CFWL_CheckBoxImp::GetPartStates()\r
324 {\r
325     FX_INT32 dwStates = FWL_PARTSTATE_CKB_UnChecked;\r
326     if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Neutral) {\r
327         dwStates = FWL_PARTSTATE_CKB_Neutral;\r
328     } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Checked) {\r
329         dwStates = FWL_PARTSTATE_CKB_Checked;\r
330     }\r
331     if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {\r
332         dwStates |= FWL_PARTSTATE_CKB_Disabled;\r
333     } else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered ) {\r
334         dwStates |= FWL_PARTSTATE_CKB_Hovered;\r
335     } else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed ) {\r
336         dwStates |= FWL_PARTSTATE_CKB_Pressed;\r
337     } else {\r
338         dwStates |= FWL_PARTSTATE_CKB_Normal;\r
339     }\r
340     if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {\r
341         dwStates |= FWL_PARTSTATE_CKB_Focused;\r
342     }\r
343     return dwStates;\r
344 }\r
345 void CFWL_CheckBoxImp::UpdateTextOutStyles()\r
346 {\r
347     m_iTTOAlign = FDE_TTOALIGNMENT_Center;\r
348     switch (m_pProperties->m_dwStyleExes & (FWL_STYLEEXT_CKB_HLayoutMask | FWL_STYLEEXT_CKB_VLayoutMask)) {\r
349         case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Top: {\r
350                 m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;\r
351                 break;\r
352             }\r
353         case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Top: {\r
354                 m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter;\r
355                 break;\r
356             }\r
357         case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Top: {\r
358                 m_iTTOAlign = FDE_TTOALIGNMENT_TopRight;\r
359                 break;\r
360             }\r
361         case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_VCenter: {\r
362                 m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;\r
363                 break;\r
364             }\r
365         case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_VCenter: {\r
366                 m_iTTOAlign = FDE_TTOALIGNMENT_Center;\r
367                 break;\r
368             }\r
369         case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_VCenter: {\r
370                 m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight;\r
371                 break;\r
372             }\r
373         case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Bottom: {\r
374                 m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft;\r
375                 break;\r
376             }\r
377         case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Bottom: {\r
378                 m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter;\r
379                 break;\r
380             }\r
381         case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Bottom: {\r
382                 m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight;\r
383                 break;\r
384             }\r
385         default: {\r
386             }\r
387     }\r
388     m_dwTTOStyles = 0;\r
389     if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) {\r
390         m_dwTTOStyles |= FDE_TTOSTYLE_RTL;\r
391     }\r
392     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine) {\r
393         m_dwTTOStyles |= FDE_TTOSTYLE_LineWrap;\r
394     } else {\r
395         m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine;\r
396     }\r
397 }\r
398 void CFWL_CheckBoxImp::NextStates()\r
399 {\r
400     FX_DWORD dwFirststate = m_pProperties->m_dwStates;\r
401     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_RadioButton) {\r
402         if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Unchecked) {\r
403             IFWL_WidgetMgr *pWMgr = FWL_GetWidgetMgr();\r
404             CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr* )pWMgr;\r
405             if (!pWidgetMgr->IsFormDisabled()) {\r
406                 CFX_PtrArray radioarr;\r
407                 pWidgetMgr->GetSameGroupRadioButton(m_pInterface, radioarr);\r
408                 IFWL_CheckBox *pCheckBox = NULL;\r
409                 FX_INT32 iCount = radioarr.GetSize();\r
410                 for (FX_INT32 i = 0; i < iCount; i++) {\r
411                     pCheckBox = (IFWL_CheckBox *)radioarr[i];\r
412                     if (pCheckBox != m_pInterface && pCheckBox->GetStates() & FWL_STATE_CKB_Checked) {\r
413                         pCheckBox->SetCheckState(0);\r
414                         CFX_RectF rt;\r
415                         pCheckBox->GetWidgetRect(rt);\r
416                         rt.left = rt.top = 0;\r
417                         m_pWidgetMgr->RepaintWidget(pCheckBox, &rt);\r
418                         break;\r
419                     }\r
420                 }\r
421             }\r
422             m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;\r
423         }\r
424     } else {\r
425         if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Neutral) {\r
426             m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;\r
427             if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) {\r
428                 m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;\r
429             }\r
430         } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) == FWL_STATE_CKB_Checked) {\r
431             m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;\r
432         } else {\r
433             if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State) {\r
434                 m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral;\r
435             } else {\r
436                 m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;\r
437             }\r
438         }\r
439     }\r
440     Repaint(&m_rtClient);\r
441     FX_DWORD dwLaststate = m_pProperties->m_dwStates;\r
442     if (dwFirststate != dwLaststate) {\r
443         CFWL_EvtCkbCheckStateChanged wmCheckBoxState;\r
444         wmCheckBoxState.m_pSrcTarget = m_pInterface;\r
445         DispatchEvent(&wmCheckBoxState);\r
446     }\r
447 }\r
448 CFWL_CheckBoxImpDelegate::CFWL_CheckBoxImpDelegate(CFWL_CheckBoxImp *pOwner)\r
449     : m_pOwner(pOwner)\r
450 {\r
451 }\r
452 FX_INT32 CFWL_CheckBoxImpDelegate::OnProcessMessage(CFWL_Message *pMessage)\r
453 {\r
454     _FWL_RETURN_VALUE_IF_FAIL(pMessage, 0);\r
455     FX_DWORD dwMsgCode = pMessage->GetClassID();\r
456     FX_INT32 iRet = 1;\r
457     switch (dwMsgCode) {\r
458         case FWL_MSGHASH_Activate: {\r
459                 OnActivate(pMessage);\r
460                 break;\r
461             }\r
462         case FWL_MSGHASH_SetFocus:\r
463         case FWL_MSGHASH_KillFocus: {\r
464                 OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);\r
465                 break;\r
466             }\r
467         case FWL_MSGHASH_Mouse: {\r
468                 CFWL_MsgMouse *pMsg = (CFWL_MsgMouse*)pMessage;\r
469                 FX_DWORD dwCmd = pMsg->m_dwCmd;\r
470                 switch (dwCmd) {\r
471                     case FWL_MSGMOUSECMD_LButtonDown: {\r
472                             OnLButtonDown(pMsg);\r
473                             break;\r
474                         }\r
475                     case FWL_MSGMOUSECMD_LButtonUp: {\r
476                             OnLButtonUp(pMsg);\r
477                             break;\r
478                         }\r
479                     case FWL_MSGMOUSECMD_MouseMove: {\r
480                             OnMouseMove(pMsg);\r
481                             break;\r
482                         }\r
483                     case FWL_MSGMOUSECMD_MouseLeave: {\r
484                             OnMouseLeave(pMsg);\r
485                             break;\r
486                         }\r
487                     default: {\r
488                         }\r
489                 }\r
490                 break;\r
491             }\r
492         case FWL_MSGHASH_Key: {\r
493                 CFWL_MsgKey *pKey = (CFWL_MsgKey*)pMessage;\r
494                 if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {\r
495                     OnKeyDown((CFWL_MsgKey*)pKey);\r
496                 }\r
497                 break;\r
498             }\r
499         default: {\r
500                 iRet = 0;\r
501             }\r
502     }\r
503     CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);\r
504     return iRet;\r
505 }\r
506 FWL_ERR CFWL_CheckBoxImpDelegate::OnDrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix)\r
507 {\r
508     return m_pOwner->DrawWidget(pGraphics, pMatrix);\r
509 }\r
510 void CFWL_CheckBoxImpDelegate::OnActivate(CFWL_Message *pMsg)\r
511 {\r
512     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Deactivated;\r
513     m_pOwner->Repaint(&(m_pOwner->m_rtClient));\r
514 }\r
515 void CFWL_CheckBoxImpDelegate::OnFocusChanged(CFWL_Message *pMsg, FX_BOOL bSet )\r
516 {\r
517     if (bSet) {\r
518         m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;\r
519     } else {\r
520         m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;\r
521     }\r
522     m_pOwner->Repaint(&(m_pOwner->m_rtClient));\r
523 }\r
524 void CFWL_CheckBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse *pMsg)\r
525 {\r
526     if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {\r
527         return;\r
528     }\r
529     if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {\r
530         m_pOwner->SetFocus(TRUE);\r
531     }\r
532     m_pOwner->m_bBtnDown = TRUE;\r
533     m_pOwner->m_pProperties->m_dwStates &= ~ FWL_STATE_CKB_Hovered;\r
534     m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed;\r
535     m_pOwner->Repaint(&(m_pOwner->m_rtClient));\r
536 }\r
537 void CFWL_CheckBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse *pMsg)\r
538 {\r
539     if (!m_pOwner->m_bBtnDown) {\r
540         return;\r
541     }\r
542     m_pOwner->m_bBtnDown = FALSE;\r
543     if (!m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
544         return;\r
545     }\r
546     m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;\r
547     m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed;\r
548     m_pOwner->NextStates();\r
549 }\r
550 void CFWL_CheckBoxImpDelegate::OnMouseMove(CFWL_MsgMouse *pMsg)\r
551 {\r
552     if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {\r
553         return;\r
554     }\r
555     FX_BOOL bRepaint = FALSE;\r
556     if (m_pOwner->m_bBtnDown) {\r
557         if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
558             if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) == 0) {\r
559                 bRepaint = TRUE;\r
560                 m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed;\r
561             }\r
562             if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered)) {\r
563                 bRepaint = TRUE;\r
564                 m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;\r
565             }\r
566         } else {\r
567             if (m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) {\r
568                 bRepaint = TRUE;\r
569                 m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed;\r
570             }\r
571             if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) {\r
572                 bRepaint = TRUE;\r
573                 m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;\r
574             }\r
575         }\r
576     } else {\r
577         if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {\r
578             if ((m_pOwner->m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) {\r
579                 bRepaint = TRUE;\r
580                 m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;\r
581             }\r
582         }\r
583     }\r
584     if (bRepaint) {\r
585         m_pOwner->Repaint(&(m_pOwner->m_rtBox));\r
586     }\r
587 }\r
588 void CFWL_CheckBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse *pMsg)\r
589 {\r
590     if (m_pOwner->m_bBtnDown) {\r
591         m_pOwner->m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;\r
592     } else {\r
593         m_pOwner->m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;\r
594     }\r
595     m_pOwner->Repaint(&(m_pOwner->m_rtBox));\r
596 }\r
597 void CFWL_CheckBoxImpDelegate::OnKeyDown(CFWL_MsgKey *pMsg)\r
598 {\r
599     if (pMsg->m_dwKeyCode == FWL_VKEY_Tab) {\r
600         m_pOwner->DispatchKeyEvent(pMsg);\r
601         return;\r
602     }\r
603     if (pMsg->m_dwKeyCode == FWL_VKEY_Return || pMsg->m_dwKeyCode == FWL_VKEY_Space) {\r
604         m_pOwner->NextStates();\r
605     }\r
606 }\r