• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fwl/cfwl_datetimepicker.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "third_party/base/ptr_util.h"
13 #include "xfa/fwl/cfwl_event.h"
14 #include "xfa/fwl/cfwl_eventselectchanged.h"
15 #include "xfa/fwl/cfwl_formproxy.h"
16 #include "xfa/fwl/cfwl_messagemouse.h"
17 #include "xfa/fwl/cfwl_messagesetfocus.h"
18 #include "xfa/fwl/cfwl_notedriver.h"
19 #include "xfa/fwl/cfwl_spinbutton.h"
20 #include "xfa/fwl/cfwl_themebackground.h"
21 #include "xfa/fwl/cfwl_widgetmgr.h"
22 #include "xfa/fwl/ifwl_themeprovider.h"
23 
24 namespace {
25 
26 const int kDateTimePickerHeight = 20;
27 
28 }  // namespace
CFWL_DateTimePicker(const CFWL_App * app)29 CFWL_DateTimePicker::CFWL_DateTimePicker(const CFWL_App* app)
30     : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
31       m_iBtnState(1),
32       m_iYear(-1),
33       m_iMonth(-1),
34       m_iDay(-1),
35       m_bLBtnDown(false) {
36   m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat;
37 
38   auto monthProp = pdfium::MakeUnique<CFWL_WidgetProperties>();
39   monthProp->m_dwStyles = FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border;
40   monthProp->m_dwStates = FWL_WGTSTATE_Invisible;
41   monthProp->m_pParent = this;
42   monthProp->m_pThemeProvider = m_pProperties->m_pThemeProvider;
43   m_pMonthCal.reset(
44       new CFWL_MonthCalendar(m_pOwnerApp, std::move(monthProp), this));
45 
46   m_pMonthCal->SetWidgetRect(
47       CFX_RectF(0, 0, m_pMonthCal->GetAutosizedWidgetRect().Size()));
48 
49   auto editProp = pdfium::MakeUnique<CFWL_WidgetProperties>();
50   editProp->m_pParent = this;
51   editProp->m_pThemeProvider = m_pProperties->m_pThemeProvider;
52 
53   m_pEdit = pdfium::MakeUnique<CFWL_DateTimeEdit>(m_pOwnerApp,
54                                                   std::move(editProp), this);
55   RegisterEventTarget(m_pMonthCal.get());
56   RegisterEventTarget(m_pEdit.get());
57 }
58 
~CFWL_DateTimePicker()59 CFWL_DateTimePicker::~CFWL_DateTimePicker() {
60   UnregisterEventTarget();
61 }
62 
GetClassID() const63 FWL_Type CFWL_DateTimePicker::GetClassID() const {
64   return FWL_Type::DateTimePicker;
65 }
66 
Update()67 void CFWL_DateTimePicker::Update() {
68   if (m_pWidgetMgr->IsFormDisabled()) {
69     DisForm_Update();
70     return;
71   }
72   if (m_iLock)
73     return;
74   if (!m_pProperties->m_pThemeProvider)
75     m_pProperties->m_pThemeProvider = GetAvailableTheme();
76 
77   m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
78   m_rtClient = GetClientRect();
79 
80   IFWL_ThemeProvider* theme = GetAvailableTheme();
81   if (!theme)
82     return;
83 
84   FX_FLOAT fBtn = theme->GetScrollBarWidth();
85   m_rtBtn = CFX_RectF(m_rtClient.right() - fBtn, m_rtClient.top, fBtn - 1,
86                       m_rtClient.height - 1);
87 
88   CFX_RectF rtEdit(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
89                    m_rtClient.height);
90   m_pEdit->SetWidgetRect(rtEdit);
91   ResetEditAlignment();
92   m_pEdit->Update();
93   if (!(m_pMonthCal->GetThemeProvider()))
94     m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
95 
96   CFX_RectF rtMonthCal = m_pMonthCal->GetAutosizedWidgetRect();
97   CFX_RectF rtPopUp(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
98                     rtMonthCal.width, rtMonthCal.height);
99   m_pMonthCal->SetWidgetRect(rtPopUp);
100   m_pMonthCal->Update();
101   return;
102 }
103 
HitTest(const CFX_PointF & point)104 FWL_WidgetHit CFWL_DateTimePicker::HitTest(const CFX_PointF& point) {
105   if (m_pWidgetMgr->IsFormDisabled())
106     return DisForm_HitTest(point);
107   if (m_rtClient.Contains(point))
108     return FWL_WidgetHit::Client;
109   if (IsMonthCalendarVisible()) {
110     CFX_RectF rect = m_pMonthCal->GetWidgetRect();
111     if (rect.Contains(point))
112       return FWL_WidgetHit::Client;
113   }
114   return FWL_WidgetHit::Unknown;
115 }
116 
DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)117 void CFWL_DateTimePicker::DrawWidget(CFX_Graphics* pGraphics,
118                                      const CFX_Matrix* pMatrix) {
119   if (!pGraphics)
120     return;
121   if (!m_pProperties->m_pThemeProvider)
122     return;
123 
124   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
125   if (HasBorder())
126     DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
127   if (!m_rtBtn.IsEmpty())
128     DrawDropDownButton(pGraphics, pTheme, pMatrix);
129   if (m_pWidgetMgr->IsFormDisabled()) {
130     DisForm_DrawWidget(pGraphics, pMatrix);
131     return;
132   }
133 }
134 
SetThemeProvider(IFWL_ThemeProvider * pTP)135 void CFWL_DateTimePicker::SetThemeProvider(IFWL_ThemeProvider* pTP) {
136   m_pProperties->m_pThemeProvider = pTP;
137   m_pMonthCal->SetThemeProvider(pTP);
138 }
139 
GetCurSel(int32_t & iYear,int32_t & iMonth,int32_t & iDay)140 void CFWL_DateTimePicker::GetCurSel(int32_t& iYear,
141                                     int32_t& iMonth,
142                                     int32_t& iDay) {
143   iYear = m_iYear;
144   iMonth = m_iMonth;
145   iDay = m_iDay;
146 }
147 
SetCurSel(int32_t iYear,int32_t iMonth,int32_t iDay)148 void CFWL_DateTimePicker::SetCurSel(int32_t iYear,
149                                     int32_t iMonth,
150                                     int32_t iDay) {
151   if (iYear <= 0 || iYear >= 3000)
152     return;
153   if (iMonth <= 0 || iMonth >= 13)
154     return;
155   if (iDay <= 0 || iDay >= 32)
156     return;
157 
158   m_iYear = iYear;
159   m_iMonth = iMonth;
160   m_iDay = iDay;
161   m_pMonthCal->SetSelect(iYear, iMonth, iDay);
162 }
163 
SetEditText(const CFX_WideString & wsText)164 void CFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) {
165   if (!m_pEdit)
166     return;
167 
168   m_pEdit->SetText(wsText);
169   RepaintRect(m_rtClient);
170 
171   CFWL_Event ev(CFWL_Event::Type::EditChanged);
172   DispatchEvent(&ev);
173 }
174 
GetEditText() const175 CFX_WideString CFWL_DateTimePicker::GetEditText() const {
176   return m_pEdit ? m_pEdit->GetText() : L"";
177 }
178 
GetBBox() const179 CFX_RectF CFWL_DateTimePicker::GetBBox() const {
180   if (m_pWidgetMgr->IsFormDisabled())
181     return DisForm_GetBBox();
182 
183   CFX_RectF rect = m_pProperties->m_rtWidget;
184   if (!IsMonthCalendarVisible())
185     return rect;
186 
187   CFX_RectF rtMonth = m_pMonthCal->GetWidgetRect();
188   rtMonth.Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top);
189   rect.Union(rtMonth);
190   return rect;
191 }
192 
ModifyEditStylesEx(uint32_t dwStylesExAdded,uint32_t dwStylesExRemoved)193 void CFWL_DateTimePicker::ModifyEditStylesEx(uint32_t dwStylesExAdded,
194                                              uint32_t dwStylesExRemoved) {
195   m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
196 }
197 
DrawDropDownButton(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)198 void CFWL_DateTimePicker::DrawDropDownButton(CFX_Graphics* pGraphics,
199                                              IFWL_ThemeProvider* pTheme,
200                                              const CFX_Matrix* pMatrix) {
201   CFWL_ThemeBackground param;
202   param.m_pWidget = this;
203   param.m_iPart = CFWL_Part::DropDownButton;
204   param.m_dwStates = m_iBtnState;
205   param.m_pGraphics = pGraphics;
206   param.m_rtPart = m_rtBtn;
207   if (pMatrix)
208     param.m_matrix.Concat(*pMatrix);
209   pTheme->DrawBackground(&param);
210 }
211 
FormatDateString(int32_t iYear,int32_t iMonth,int32_t iDay,CFX_WideString & wsText)212 void CFWL_DateTimePicker::FormatDateString(int32_t iYear,
213                                            int32_t iMonth,
214                                            int32_t iDay,
215                                            CFX_WideString& wsText) {
216   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat) ==
217       FWL_STYLEEXT_DTP_ShortDateFormat) {
218     wsText.Format(L"%d-%d-%d", iYear, iMonth, iDay);
219   } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) ==
220              FWL_STYLEEXT_DTP_LongDateFormat) {
221     wsText.Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay);
222   }
223 }
224 
ShowMonthCalendar(bool bActivate)225 void CFWL_DateTimePicker::ShowMonthCalendar(bool bActivate) {
226   if (m_pWidgetMgr->IsFormDisabled())
227     return DisForm_ShowMonthCalendar(bActivate);
228   if (IsMonthCalendarVisible() == bActivate)
229     return;
230   if (!m_pForm)
231     InitProxyForm();
232 
233   if (!bActivate) {
234     m_pForm->EndDoModal();
235     return;
236   }
237 
238   CFX_RectF rtMonth = m_pMonthCal->GetWidgetRect();
239 
240   CFX_RectF rtAnchor(0, 0, m_pProperties->m_rtWidget.width,
241                      m_pProperties->m_rtWidget.height);
242   GetPopupPos(0, rtMonth.height, rtAnchor, rtMonth);
243   m_pForm->SetWidgetRect(rtMonth);
244 
245   rtMonth.left = rtMonth.top = 0;
246   if (bActivate)
247     m_pMonthCal->RemoveStates(FWL_WGTSTATE_Invisible);
248   else
249     m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible);
250   m_pMonthCal->SetWidgetRect(rtMonth);
251   m_pMonthCal->Update();
252   m_pForm->DoModal();
253 }
254 
IsMonthCalendarVisible() const255 bool CFWL_DateTimePicker::IsMonthCalendarVisible() const {
256   if (m_pWidgetMgr->IsFormDisabled())
257     return DisForm_IsMonthCalendarVisible();
258   if (!m_pForm)
259     return false;
260   return !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);
261 }
262 
ResetEditAlignment()263 void CFWL_DateTimePicker::ResetEditAlignment() {
264   if (!m_pEdit)
265     return;
266 
267   uint32_t dwAdd = 0;
268   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditHAlignMask) {
269     case FWL_STYLEEXT_DTP_EditHCenter: {
270       dwAdd |= FWL_STYLEEXT_EDT_HCenter;
271       break;
272     }
273     case FWL_STYLEEXT_DTP_EditHFar: {
274       dwAdd |= FWL_STYLEEXT_EDT_HFar;
275       break;
276     }
277     default: {
278       dwAdd |= FWL_STYLEEXT_EDT_HNear;
279       break;
280     }
281   }
282   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditVAlignMask) {
283     case FWL_STYLEEXT_DTP_EditVCenter: {
284       dwAdd |= FWL_STYLEEXT_EDT_VCenter;
285       break;
286     }
287     case FWL_STYLEEXT_DTP_EditVFar: {
288       dwAdd |= FWL_STYLEEXT_EDT_VFar;
289       break;
290     }
291     default: {
292       dwAdd |= FWL_STYLEEXT_EDT_VNear;
293       break;
294     }
295   }
296   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditJustified)
297     dwAdd |= FWL_STYLEEXT_EDT_Justified;
298 
299   m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
300                                      FWL_STYLEEXT_EDT_HAlignModeMask |
301                                      FWL_STYLEEXT_EDT_VAlignMask);
302 }
303 
ProcessSelChanged(int32_t iYear,int32_t iMonth,int32_t iDay)304 void CFWL_DateTimePicker::ProcessSelChanged(int32_t iYear,
305                                             int32_t iMonth,
306                                             int32_t iDay) {
307   m_iYear = iYear;
308   m_iMonth = iMonth;
309   m_iDay = iDay;
310 
311   CFX_WideString wsText;
312   FormatDateString(m_iYear, m_iMonth, m_iDay, wsText);
313   m_pEdit->SetText(wsText);
314   m_pEdit->Update();
315   RepaintRect(m_rtClient);
316 
317   CFWL_EventSelectChanged ev(this);
318   ev.iYear = m_iYear;
319   ev.iMonth = m_iMonth;
320   ev.iDay = m_iDay;
321   DispatchEvent(&ev);
322 }
323 
InitProxyForm()324 void CFWL_DateTimePicker::InitProxyForm() {
325   if (m_pForm)
326     return;
327   if (!m_pMonthCal)
328     return;
329 
330   auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
331   prop->m_dwStyles = FWL_WGTSTYLE_Popup;
332   prop->m_dwStates = FWL_WGTSTATE_Invisible;
333   prop->m_pOwner = this;
334 
335   m_pForm = pdfium::MakeUnique<CFWL_FormProxy>(m_pOwnerApp, std::move(prop),
336                                                m_pMonthCal.get());
337   m_pMonthCal->SetParent(m_pForm.get());
338 }
339 
DisForm_IsMonthCalendarVisible() const340 bool CFWL_DateTimePicker::DisForm_IsMonthCalendarVisible() const {
341   if (!m_pMonthCal)
342     return false;
343   return !(m_pMonthCal->GetStates() & FWL_WGTSTATE_Invisible);
344 }
345 
DisForm_ShowMonthCalendar(bool bActivate)346 void CFWL_DateTimePicker::DisForm_ShowMonthCalendar(bool bActivate) {
347   if (IsMonthCalendarVisible() == bActivate)
348     return;
349 
350   if (bActivate) {
351     CFX_RectF rtMonthCal = m_pMonthCal->GetAutosizedWidgetRect();
352     FX_FLOAT fPopupMin = rtMonthCal.height;
353     FX_FLOAT fPopupMax = rtMonthCal.height;
354     CFX_RectF rtAnchor(m_pProperties->m_rtWidget);
355     rtAnchor.width = rtMonthCal.width;
356     rtMonthCal.left = m_rtClient.left;
357     rtMonthCal.top = rtAnchor.Height();
358     GetPopupPos(fPopupMin, fPopupMax, rtAnchor, rtMonthCal);
359     m_pMonthCal->SetWidgetRect(rtMonthCal);
360     if (m_iYear > 0 && m_iMonth > 0 && m_iDay > 0)
361       m_pMonthCal->SetSelect(m_iYear, m_iMonth, m_iDay);
362     m_pMonthCal->Update();
363   }
364   if (bActivate)
365     m_pMonthCal->RemoveStates(FWL_WGTSTATE_Invisible);
366   else
367     m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible);
368 
369   if (bActivate) {
370     CFWL_MessageSetFocus msg(m_pEdit.get(), m_pMonthCal.get());
371     m_pEdit->GetDelegate()->OnProcessMessage(&msg);
372   }
373 
374   CFX_RectF rtInvalidate(0, 0, m_pProperties->m_rtWidget.width,
375                          m_pProperties->m_rtWidget.height);
376 
377   CFX_RectF rtCal = m_pMonthCal->GetWidgetRect();
378   rtInvalidate.Union(rtCal);
379   rtInvalidate.Inflate(2, 2);
380   RepaintRect(rtInvalidate);
381 }
382 
DisForm_HitTest(const CFX_PointF & point) const383 FWL_WidgetHit CFWL_DateTimePicker::DisForm_HitTest(
384     const CFX_PointF& point) const {
385   CFX_RectF rect(0, 0, m_pProperties->m_rtWidget.width,
386                  m_pProperties->m_rtWidget.height);
387   if (rect.Contains(point))
388     return FWL_WidgetHit::Edit;
389   if (DisForm_IsNeedShowButton())
390     rect.width += m_fBtn;
391   if (rect.Contains(point))
392     return FWL_WidgetHit::Client;
393   if (IsMonthCalendarVisible()) {
394     if (m_pMonthCal->GetWidgetRect().Contains(point))
395       return FWL_WidgetHit::Client;
396   }
397   return FWL_WidgetHit::Unknown;
398 }
399 
DisForm_IsNeedShowButton() const400 bool CFWL_DateTimePicker::DisForm_IsNeedShowButton() const {
401   return m_pProperties->m_dwStates & FWL_WGTSTATE_Focused ||
402          m_pMonthCal->GetStates() & FWL_WGTSTATE_Focused ||
403          m_pEdit->GetStates() & FWL_WGTSTATE_Focused;
404 }
405 
DisForm_Update()406 void CFWL_DateTimePicker::DisForm_Update() {
407   if (m_iLock)
408     return;
409   if (!m_pProperties->m_pThemeProvider)
410     m_pProperties->m_pThemeProvider = GetAvailableTheme();
411 
412   m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
413   m_rtClient = GetClientRect();
414   m_pEdit->SetWidgetRect(m_rtClient);
415   ResetEditAlignment();
416   m_pEdit->Update();
417 
418   if (!m_pMonthCal->GetThemeProvider())
419     m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
420 
421   IFWL_ThemeProvider* theme = GetAvailableTheme();
422   if (!theme)
423     return;
424 
425   m_fBtn = theme->GetScrollBarWidth();
426   CFX_RectF rtMonthCal = m_pMonthCal->GetAutosizedWidgetRect();
427   CFX_RectF rtPopUp(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
428                     rtMonthCal.width, rtMonthCal.height);
429   m_pMonthCal->SetWidgetRect(rtPopUp);
430   m_pMonthCal->Update();
431 }
432 
DisForm_GetBBox() const433 CFX_RectF CFWL_DateTimePicker::DisForm_GetBBox() const {
434   CFX_RectF rect = m_pProperties->m_rtWidget;
435   if (DisForm_IsNeedShowButton())
436     rect.width += m_fBtn;
437   if (!IsMonthCalendarVisible())
438     return rect;
439 
440   CFX_RectF rtMonth = m_pMonthCal->GetWidgetRect();
441   rtMonth.Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top);
442   rect.Union(rtMonth);
443   return rect;
444 }
445 
DisForm_DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)446 void CFWL_DateTimePicker::DisForm_DrawWidget(CFX_Graphics* pGraphics,
447                                              const CFX_Matrix* pMatrix) {
448   if (!pGraphics)
449     return;
450   if (m_pEdit) {
451     CFX_RectF rtEdit = m_pEdit->GetWidgetRect();
452 
453     CFX_Matrix mt(1, 0, 0, 1, rtEdit.left, rtEdit.top);
454     if (pMatrix)
455       mt.Concat(*pMatrix);
456     m_pEdit->DrawWidget(pGraphics, &mt);
457   }
458   if (!IsMonthCalendarVisible())
459     return;
460 
461   CFX_RectF rtMonth = m_pMonthCal->GetWidgetRect();
462   CFX_Matrix mt(1, 0, 0, 1, rtMonth.left, rtMonth.top);
463   if (pMatrix)
464     mt.Concat(*pMatrix);
465   m_pMonthCal->DrawWidget(pGraphics, &mt);
466 }
467 
OnProcessMessage(CFWL_Message * pMessage)468 void CFWL_DateTimePicker::OnProcessMessage(CFWL_Message* pMessage) {
469   if (!pMessage)
470     return;
471 
472   switch (pMessage->GetType()) {
473     case CFWL_Message::Type::SetFocus:
474       OnFocusChanged(pMessage, true);
475       break;
476     case CFWL_Message::Type::KillFocus:
477       OnFocusChanged(pMessage, false);
478       break;
479     case CFWL_Message::Type::Mouse: {
480       CFWL_MessageMouse* pMouse = static_cast<CFWL_MessageMouse*>(pMessage);
481       switch (pMouse->m_dwCmd) {
482         case FWL_MouseCommand::LeftButtonDown:
483           OnLButtonDown(pMouse);
484           break;
485         case FWL_MouseCommand::LeftButtonUp:
486           OnLButtonUp(pMouse);
487           break;
488         case FWL_MouseCommand::Move:
489           OnMouseMove(pMouse);
490           break;
491         case FWL_MouseCommand::Leave:
492           OnMouseLeave(pMouse);
493           break;
494         default:
495           break;
496       }
497       break;
498     }
499     case CFWL_Message::Type::Key: {
500       if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
501         m_pEdit->GetDelegate()->OnProcessMessage(pMessage);
502         return;
503       }
504       break;
505     }
506     default:
507       break;
508   }
509 
510   CFWL_Widget::OnProcessMessage(pMessage);
511 }
512 
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)513 void CFWL_DateTimePicker::OnDrawWidget(CFX_Graphics* pGraphics,
514                                        const CFX_Matrix* pMatrix) {
515   DrawWidget(pGraphics, pMatrix);
516 }
517 
OnFocusChanged(CFWL_Message * pMsg,bool bSet)518 void CFWL_DateTimePicker::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
519   if (!pMsg)
520     return;
521   if (m_pWidgetMgr->IsFormDisabled())
522     return DisForm_OnFocusChanged(pMsg, bSet);
523 
524   if (bSet) {
525     m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
526     RepaintRect(m_rtClient);
527   } else {
528     m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
529     RepaintRect(m_rtClient);
530   }
531   if (pMsg->m_pSrcTarget == m_pMonthCal.get() && IsMonthCalendarVisible()) {
532     ShowMonthCalendar(false);
533   }
534   RepaintRect(m_rtClient);
535 }
536 
OnLButtonDown(CFWL_MessageMouse * pMsg)537 void CFWL_DateTimePicker::OnLButtonDown(CFWL_MessageMouse* pMsg) {
538   if (!pMsg)
539     return;
540   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
541     SetFocus(true);
542   if (!m_rtBtn.Contains(pMsg->m_pos))
543     return;
544 
545   if (IsMonthCalendarVisible()) {
546     ShowMonthCalendar(false);
547     return;
548   }
549   ShowMonthCalendar(true);
550 
551   m_bLBtnDown = true;
552   RepaintRect(m_rtClient);
553 }
554 
OnLButtonUp(CFWL_MessageMouse * pMsg)555 void CFWL_DateTimePicker::OnLButtonUp(CFWL_MessageMouse* pMsg) {
556   if (!pMsg)
557     return;
558 
559   m_bLBtnDown = false;
560   if (m_rtBtn.Contains(pMsg->m_pos))
561     m_iBtnState = CFWL_PartState_Hovered;
562   else
563     m_iBtnState = CFWL_PartState_Normal;
564   RepaintRect(m_rtBtn);
565 }
566 
OnMouseMove(CFWL_MessageMouse * pMsg)567 void CFWL_DateTimePicker::OnMouseMove(CFWL_MessageMouse* pMsg) {
568   if (!m_rtBtn.Contains(pMsg->m_pos))
569     m_iBtnState = CFWL_PartState_Normal;
570   RepaintRect(m_rtBtn);
571 }
572 
OnMouseLeave(CFWL_MessageMouse * pMsg)573 void CFWL_DateTimePicker::OnMouseLeave(CFWL_MessageMouse* pMsg) {
574   if (!pMsg)
575     return;
576   m_iBtnState = CFWL_PartState_Normal;
577   RepaintRect(m_rtBtn);
578 }
579 
DisForm_OnFocusChanged(CFWL_Message * pMsg,bool bSet)580 void CFWL_DateTimePicker::DisForm_OnFocusChanged(CFWL_Message* pMsg,
581                                                  bool bSet) {
582   CFX_RectF rtInvalidate(m_rtBtn);
583   if (bSet) {
584     m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
585     if (m_pEdit && !(m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)) {
586       m_rtBtn = CFX_RectF(m_pProperties->m_rtWidget.width, 0, m_fBtn,
587                           m_pProperties->m_rtWidget.height - 1);
588     }
589     rtInvalidate = m_rtBtn;
590     pMsg->m_pDstTarget = m_pEdit.get();
591     m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
592   } else {
593     m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
594     m_rtBtn.Reset();
595 
596     if (DisForm_IsMonthCalendarVisible())
597       ShowMonthCalendar(false);
598     if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
599       pMsg->m_pSrcTarget = m_pEdit.get();
600       m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
601     }
602   }
603   rtInvalidate.Inflate(2, 2);
604   RepaintRect(rtInvalidate);
605 }
606