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