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/src/foxitlib.h"
8 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
9 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
10 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
11 #include "xfa/src/fwl/src/core/include/fwl_panelimp.h"
12 #include "xfa/src/fwl/src/core/include/fwl_formimp.h"
13 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
14 #include "xfa/src/fwl/src/basewidget/include/fwl_formproxyimp.h"
15 #include "xfa/src/fwl/src/basewidget/include/fwl_editimp.h"
16 #include "xfa/src/fwl/src/basewidget/include/fwl_monthcalendarimp.h"
17 #include "xfa/src/fwl/src/basewidget/include/fwl_datetimepickerimp.h"
18 #define FWL_DTP_WIDTH 100
19 #define FWL_DTP_HEIGHT 20
20 
21 // static
Create(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)22 IFWL_DateTimePicker* IFWL_DateTimePicker::Create(
23     const CFWL_WidgetImpProperties& properties,
24     IFWL_Widget* pOuter) {
25   IFWL_DateTimePicker* pDateTimePicker = new IFWL_DateTimePicker;
26   CFWL_DateTimePickerImp* pDateTimePickerImpl =
27       new CFWL_DateTimePickerImp(properties, pOuter);
28   pDateTimePicker->SetImpl(pDateTimePickerImpl);
29   pDateTimePickerImpl->SetInterface(pDateTimePicker);
30   return pDateTimePicker;
31 }
32 
33 // Static
Create(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)34 IFWL_DateTimeForm* IFWL_DateTimeForm::Create(
35     const CFWL_WidgetImpProperties& properties,
36     IFWL_Widget* pOuter) {
37   IFWL_DateTimeForm* pDateTimeForm = new IFWL_DateTimeForm;
38   CFWL_FormProxyImp* pFormProxyImpl = new CFWL_FormProxyImp(properties, pOuter);
39   pDateTimeForm->SetImpl(pFormProxyImpl);
40   pFormProxyImpl->SetInterface(pDateTimeForm);
41   return pDateTimeForm;
42 }
43 
44 // static
Create(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)45 IFWL_DateTimeCalender* IFWL_DateTimeCalender::Create(
46     const CFWL_WidgetImpProperties& properties,
47     IFWL_Widget* pOuter) {
48   IFWL_DateTimeCalender* pDateTimeCalendar = new IFWL_DateTimeCalender;
49   CFWL_DateTimeCalendar* pDateTimeCalendarImpl =
50       new CFWL_DateTimeCalendar(properties, pOuter);
51   pDateTimeCalendar->SetImpl(pDateTimeCalendarImpl);
52   pDateTimeCalendarImpl->SetInterface(pDateTimeCalendar);
53   return pDateTimeCalendar;
54 }
55 
56 // static
Create(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)57 IFWL_DateTimeEdit* IFWL_DateTimeEdit::Create(
58     const CFWL_WidgetImpProperties& properties,
59     IFWL_Widget* pOuter) {
60   IFWL_DateTimeEdit* pDateTimeEdit = new IFWL_DateTimeEdit;
61   CFWL_DateTimeEdit* pDateTimeEditImpl =
62       new CFWL_DateTimeEdit(properties, pOuter);
63   pDateTimeEdit->SetImpl(pDateTimeEditImpl);
64   pDateTimeEditImpl->SetInterface(pDateTimeEdit);
65   return pDateTimeEdit;
66 }
67 
IFWL_DateTimePicker()68 IFWL_DateTimePicker::IFWL_DateTimePicker() {
69 }
CountSelRanges()70 int32_t IFWL_DateTimePicker::CountSelRanges() {
71   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
72       ->GetDataTimeEdit()
73       ->CountSelRanges();
74 }
GetSelRange(int32_t nIndex,int32_t & nStart)75 int32_t IFWL_DateTimePicker::GetSelRange(int32_t nIndex, int32_t& nStart) {
76   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
77       ->GetDataTimeEdit()
78       ->GetSelRange(nIndex, nStart);
79 }
GetCurSel(int32_t & iYear,int32_t & iMonth,int32_t & iDay)80 FWL_ERR IFWL_DateTimePicker::GetCurSel(int32_t& iYear,
81                                        int32_t& iMonth,
82                                        int32_t& iDay) {
83   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
84       ->GetCurSel(iYear, iMonth, iDay);
85 }
SetCurSel(int32_t iYear,int32_t iMonth,int32_t iDay)86 FWL_ERR IFWL_DateTimePicker::SetCurSel(int32_t iYear,
87                                        int32_t iMonth,
88                                        int32_t iDay) {
89   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
90       ->SetCurSel(iYear, iMonth, iDay);
91 }
SetEditText(const CFX_WideString & wsText)92 FWL_ERR IFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) {
93   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SetEditText(wsText);
94 }
GetEditText(CFX_WideString & wsText,int32_t nStart,int32_t nCount) const95 FWL_ERR IFWL_DateTimePicker::GetEditText(CFX_WideString& wsText,
96                                          int32_t nStart,
97                                          int32_t nCount) const {
98   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
99       ->GetEditText(wsText, nStart, nCount);
100 }
CanUndo()101 FX_BOOL IFWL_DateTimePicker::CanUndo() {
102   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanUndo();
103 }
CanRedo()104 FX_BOOL IFWL_DateTimePicker::CanRedo() {
105   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanRedo();
106 }
Undo()107 FX_BOOL IFWL_DateTimePicker::Undo() {
108   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Undo();
109 }
Redo()110 FX_BOOL IFWL_DateTimePicker::Redo() {
111   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Redo();
112 }
CanCopy()113 FX_BOOL IFWL_DateTimePicker::CanCopy() {
114   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanCopy();
115 }
CanCut()116 FX_BOOL IFWL_DateTimePicker::CanCut() {
117   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanCut();
118 }
CanSelectAll()119 FX_BOOL IFWL_DateTimePicker::CanSelectAll() {
120   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanSelectAll();
121 }
Copy(CFX_WideString & wsCopy)122 FX_BOOL IFWL_DateTimePicker::Copy(CFX_WideString& wsCopy) {
123   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Copy(wsCopy);
124 }
Cut(CFX_WideString & wsCut)125 FX_BOOL IFWL_DateTimePicker::Cut(CFX_WideString& wsCut) {
126   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Cut(wsCut);
127 }
Paste(const CFX_WideString & wsPaste)128 FX_BOOL IFWL_DateTimePicker::Paste(const CFX_WideString& wsPaste) {
129   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Paste(wsPaste);
130 }
SelectAll()131 FX_BOOL IFWL_DateTimePicker::SelectAll() {
132   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SelectAll();
133 }
Delete()134 FX_BOOL IFWL_DateTimePicker::Delete() {
135   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Delete();
136 }
DeSelect()137 FX_BOOL IFWL_DateTimePicker::DeSelect() {
138   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->DeSelect();
139 }
GetBBox(CFX_RectF & rect)140 FWL_ERR IFWL_DateTimePicker::GetBBox(CFX_RectF& rect) {
141   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->GetBBox(rect);
142 }
SetEditLimit(int32_t nLimit)143 FWL_ERR IFWL_DateTimePicker::SetEditLimit(int32_t nLimit) {
144   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SetEditLimit(nLimit);
145 }
ModifyEditStylesEx(FX_DWORD dwStylesExAdded,FX_DWORD dwStylesExRemoved)146 FWL_ERR IFWL_DateTimePicker::ModifyEditStylesEx(FX_DWORD dwStylesExAdded,
147                                                 FX_DWORD dwStylesExRemoved) {
148   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
149       ->ModifyEditStylesEx(dwStylesExAdded, dwStylesExRemoved);
150 }
CFWL_DateTimeEdit(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)151 CFWL_DateTimeEdit::CFWL_DateTimeEdit(const CFWL_WidgetImpProperties& properties,
152                                      IFWL_Widget* pOuter)
153     : CFWL_EditImp(properties, pOuter) {}
Initialize()154 FWL_ERR CFWL_DateTimeEdit::Initialize() {
155   m_pDelegate = new CFWL_DateTimeEditImpDelegate(this);
156   if (CFWL_EditImp::Initialize() != FWL_ERR_Succeeded)
157     return FWL_ERR_Indefinite;
158   return FWL_ERR_Succeeded;
159 }
Finalize()160 FWL_ERR CFWL_DateTimeEdit::Finalize() {
161   delete m_pDelegate;
162   m_pDelegate = nullptr;
163   return CFWL_EditImp::Finalize();
164 }
CFWL_DateTimeEditImpDelegate(CFWL_DateTimeEdit * pOwner)165 CFWL_DateTimeEditImpDelegate::CFWL_DateTimeEditImpDelegate(
166     CFWL_DateTimeEdit* pOwner)
167     : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) {
168 }
OnProcessMessage(CFWL_Message * pMessage)169 int32_t CFWL_DateTimeEditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
170   if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
171     return DisForm_OnProcessMessage(pMessage);
172   }
173   FX_DWORD dwHashCode = pMessage->GetClassID();
174   if (dwHashCode == FWL_MSGHASH_SetFocus ||
175       dwHashCode == FWL_MSGHASH_KillFocus) {
176     IFWL_Widget* pOuter = m_pOwner->GetOuter();
177     IFWL_WidgetDelegate* pDelegate = pOuter->SetDelegate(NULL);
178     pDelegate->OnProcessMessage(pMessage);
179   }
180   return 1;
181 }
DisForm_OnProcessMessage(CFWL_Message * pMessage)182 int32_t CFWL_DateTimeEditImpDelegate::DisForm_OnProcessMessage(
183     CFWL_Message* pMessage) {
184   FX_DWORD dwHashCode = pMessage->GetClassID();
185   if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
186     if (dwHashCode == FWL_MSGHASH_Mouse) {
187       CFWL_MsgMouse* pMouse = static_cast<CFWL_MsgMouse*>(pMessage);
188       if (pMouse->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown ||
189           pMouse->m_dwCmd == FWL_MSGMOUSECMD_RButtonDown) {
190         if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
191           m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
192         }
193         CFWL_DateTimePickerImp* pDateTime =
194             static_cast<CFWL_DateTimePickerImp*>(m_pOwner->m_pOuter->GetImpl());
195         if (pDateTime->IsMonthCalendarShowed()) {
196           CFX_RectF rtInvalidate;
197           pDateTime->GetWidgetRect(rtInvalidate);
198           pDateTime->ShowMonthCalendar(FALSE);
199           rtInvalidate.Offset(-rtInvalidate.left, -rtInvalidate.top);
200           pDateTime->Repaint(&rtInvalidate);
201         }
202       }
203     } else if (dwHashCode == FWL_MSGHASH_Key) {
204       return CFWL_EditImpDelegate::OnProcessMessage(pMessage);
205     }
206   }
207   return CFWL_EditImpDelegate::OnProcessMessage(pMessage);
208 }
CFWL_DateTimeCalendar(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)209 CFWL_DateTimeCalendar::CFWL_DateTimeCalendar(
210     const CFWL_WidgetImpProperties& properties,
211     IFWL_Widget* pOuter)
212     : CFWL_MonthCalendarImp(properties, pOuter) {}
Initialize()213 FWL_ERR CFWL_DateTimeCalendar::Initialize() {
214   if (CFWL_MonthCalendarImp::Initialize() != FWL_ERR_Succeeded)
215     return FWL_ERR_Indefinite;
216   delete m_pDelegate;
217   m_pDelegate = new CFWL_DateTimeCalendarImpDelegate(this);
218   return FWL_ERR_Succeeded;
219 }
Finalize()220 FWL_ERR CFWL_DateTimeCalendar::Finalize() {
221   delete m_pDelegate;
222   m_pDelegate = nullptr;
223   return CFWL_MonthCalendarImp::Finalize();
224 }
CFWL_DateTimeCalendarImpDelegate(CFWL_DateTimeCalendar * pOwner)225 CFWL_DateTimeCalendarImpDelegate::CFWL_DateTimeCalendarImpDelegate(
226     CFWL_DateTimeCalendar* pOwner)
227     : CFWL_MonthCalendarImpDelegate(pOwner), m_pOwner(pOwner) {
228   m_bFlag = FALSE;
229 }
OnProcessMessage(CFWL_Message * pMessage)230 int32_t CFWL_DateTimeCalendarImpDelegate::OnProcessMessage(
231     CFWL_Message* pMessage) {
232   FX_DWORD dwCode = pMessage->GetClassID();
233   if (dwCode == FWL_MSGHASH_SetFocus || dwCode == FWL_MSGHASH_KillFocus) {
234     IFWL_Widget* pOuter = m_pOwner->GetOuter();
235     IFWL_WidgetDelegate* pDelegate = pOuter->SetDelegate(NULL);
236     return pDelegate->OnProcessMessage(pMessage);
237   } else if (dwCode == FWL_MSGHASH_Mouse) {
238     CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
239     if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) {
240       OnLButtonDownEx(pMsg);
241       return 1;
242     } else if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonUp) {
243       OnLButtonUpEx(pMsg);
244       return 1;
245     }
246   }
247   return CFWL_MonthCalendarImpDelegate::OnProcessMessage(pMessage);
248 }
OnLButtonDownEx(CFWL_MsgMouse * pMsg)249 void CFWL_DateTimeCalendarImpDelegate::OnLButtonDownEx(CFWL_MsgMouse* pMsg) {
250   if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
251     m_pOwner->m_iLBtnPartStates = FWL_PARTSTATE_MCD_Pressed;
252     m_pOwner->PrevMonth();
253     m_pOwner->Repaint(&m_pOwner->m_rtClient);
254   } else if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
255     m_pOwner->m_iRBtnPartStates |= FWL_PARTSTATE_MCD_Pressed;
256     m_pOwner->NextMonth();
257     m_pOwner->Repaint(&m_pOwner->m_rtClient);
258   } else if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) {
259     if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_NoToday) ==
260         0) {
261       m_pOwner->JumpToToday();
262       m_pOwner->Repaint(&m_pOwner->m_rtClient);
263     }
264   } else {
265     IFWL_DateTimePicker* pIPicker =
266         static_cast<IFWL_DateTimePicker*>(m_pOwner->m_pOuter);
267     CFWL_DateTimePickerImp* pPicker =
268         static_cast<CFWL_DateTimePickerImp*>(pIPicker->GetImpl());
269     if (pPicker->IsMonthCalendarShowed()) {
270       m_bFlag = 1;
271     }
272   }
273 }
OnLButtonUpEx(CFWL_MsgMouse * pMsg)274 void CFWL_DateTimeCalendarImpDelegate::OnLButtonUpEx(CFWL_MsgMouse* pMsg) {
275   if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
276     return DisForm_OnLButtonUpEx(pMsg);
277   }
278   if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
279     m_pOwner->m_iLBtnPartStates = 0;
280     m_pOwner->Repaint(&m_pOwner->m_rtLBtn);
281     return;
282   }
283   if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
284     m_pOwner->m_iRBtnPartStates = 0;
285     m_pOwner->Repaint(&m_pOwner->m_rtRBtn);
286     return;
287   }
288   if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) {
289     return;
290   }
291   int32_t iOldSel = 0;
292   if (m_pOwner->m_arrSelDays.GetSize() > 0) {
293     iOldSel = m_pOwner->m_arrSelDays[0];
294   }
295   int32_t iCurSel = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy);
296   CFX_RectF rt;
297   IFWL_DateTimePicker* pIPicker =
298       static_cast<IFWL_DateTimePicker*>(m_pOwner->m_pOuter);
299   CFWL_DateTimePickerImp* pPicker =
300       static_cast<CFWL_DateTimePickerImp*>(pIPicker->GetImpl());
301   pPicker->m_pForm->GetWidgetRect(rt);
302   rt.Set(0, 0, rt.width, rt.height);
303   if (iCurSel > 0) {
304     LPDATEINFO lpDatesInfo =
305         (LPDATEINFO)m_pOwner->m_arrDates.GetAt(iCurSel - 1);
306     CFX_RectF rtInvalidate(lpDatesInfo->rect);
307     if (iOldSel > 0 && iOldSel <= m_pOwner->m_arrDates.GetSize()) {
308       lpDatesInfo = (LPDATEINFO)m_pOwner->m_arrDates.GetAt(iOldSel - 1);
309       rtInvalidate.Union(lpDatesInfo->rect);
310     }
311     m_pOwner->AddSelDay(iCurSel);
312     if (!m_pOwner->m_pOuter)
313       return;
314     pPicker->ProcessSelChanged(m_pOwner->m_iCurYear, m_pOwner->m_iCurMonth,
315                                iCurSel);
316     pPicker->ShowMonthCalendar(FALSE);
317   } else if (m_bFlag && (!rt.Contains(pMsg->m_fx, pMsg->m_fy))) {
318     IFWL_DateTimePicker* pIPicker =
319         static_cast<IFWL_DateTimePicker*>(m_pOwner->m_pOuter);
320     CFWL_DateTimePickerImp* pPicker =
321         static_cast<CFWL_DateTimePickerImp*>(pIPicker->GetImpl());
322     pPicker->ShowMonthCalendar(FALSE);
323   }
324   m_bFlag = 0;
325 }
OnMouseMoveEx(CFWL_MsgMouse * pMsg)326 void CFWL_DateTimeCalendarImpDelegate::OnMouseMoveEx(CFWL_MsgMouse* pMsg) {
327   if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_MCD_MultiSelect) {
328     return;
329   }
330   FX_BOOL bRepaint = FALSE;
331   CFX_RectF rtInvalidate;
332   rtInvalidate.Set(0, 0, 0, 0);
333   if (m_pOwner->m_rtDates.Contains(pMsg->m_fx, pMsg->m_fy)) {
334     int32_t iHover = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy);
335     bRepaint = m_pOwner->m_iHovered != iHover;
336     if (bRepaint) {
337       if (m_pOwner->m_iHovered > 0) {
338         m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate);
339       }
340       if (iHover > 0) {
341         CFX_RectF rtDay;
342         m_pOwner->GetDayRect(iHover, rtDay);
343         if (rtInvalidate.IsEmpty()) {
344           rtInvalidate = rtDay;
345         } else {
346           rtInvalidate.Union(rtDay);
347         }
348       }
349     }
350     m_pOwner->m_iHovered = iHover;
351     CFWL_Event_DtpHoverChanged ev;
352     ev.hoverday = iHover;
353     m_pOwner->DispatchEvent(&ev);
354   } else {
355     bRepaint = m_pOwner->m_iHovered > 0;
356     if (bRepaint) {
357       m_pOwner->GetDayRect(m_pOwner->m_iHovered, rtInvalidate);
358     }
359     m_pOwner->m_iHovered = -1;
360   }
361   if (bRepaint && !rtInvalidate.IsEmpty()) {
362     m_pOwner->Repaint(&rtInvalidate);
363   }
364 }
DisForm_OnProcessMessage(CFWL_Message * pMessage)365 int32_t CFWL_DateTimeCalendarImpDelegate::DisForm_OnProcessMessage(
366     CFWL_Message* pMessage) {
367   if (pMessage->GetClassID() == FWL_MSGHASH_Mouse) {
368     CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
369     if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonUp) {
370       DisForm_OnLButtonUpEx(pMsg);
371       return 1;
372     }
373   }
374   return CFWL_MonthCalendarImpDelegate::OnProcessMessage(pMessage);
375 }
DisForm_OnLButtonUpEx(CFWL_MsgMouse * pMsg)376 void CFWL_DateTimeCalendarImpDelegate::DisForm_OnLButtonUpEx(
377     CFWL_MsgMouse* pMsg) {
378   if (m_pOwner->m_rtLBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
379     m_pOwner->m_iLBtnPartStates = 0;
380     m_pOwner->Repaint(&(m_pOwner->m_rtLBtn));
381     return;
382   }
383   if (m_pOwner->m_rtRBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
384     m_pOwner->m_iRBtnPartStates = 0;
385     m_pOwner->Repaint(&(m_pOwner->m_rtRBtn));
386     return;
387   }
388   if (m_pOwner->m_rtToday.Contains(pMsg->m_fx, pMsg->m_fy)) {
389     return;
390   }
391   int32_t iOldSel = 0;
392   if (m_pOwner->m_arrSelDays.GetSize() > 0) {
393     iOldSel = m_pOwner->m_arrSelDays[0];
394   }
395   int32_t iCurSel = m_pOwner->GetDayAtPoint(pMsg->m_fx, pMsg->m_fy);
396   if (iCurSel > 0) {
397     LPDATEINFO lpDatesInfo =
398         (LPDATEINFO)m_pOwner->m_arrDates.GetAt(iCurSel - 1);
399     CFX_RectF rtInvalidate(lpDatesInfo->rect);
400     if (iOldSel > 0 && iOldSel <= m_pOwner->m_arrDates.GetSize()) {
401       lpDatesInfo = (LPDATEINFO)m_pOwner->m_arrDates.GetAt(iOldSel - 1);
402       rtInvalidate.Union(lpDatesInfo->rect);
403     }
404     m_pOwner->AddSelDay(iCurSel);
405     CFWL_DateTimePickerImp* pDateTime =
406         static_cast<CFWL_DateTimePickerImp*>(m_pOwner->m_pOuter->GetImpl());
407     pDateTime->ProcessSelChanged(m_pOwner->m_iCurYear, m_pOwner->m_iCurMonth,
408                                  iCurSel);
409     pDateTime->ShowMonthCalendar(FALSE);
410   }
411 }
CFWL_DateTimePickerImp(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)412 CFWL_DateTimePickerImp::CFWL_DateTimePickerImp(
413     const CFWL_WidgetImpProperties& properties,
414     IFWL_Widget* pOuter)
415     : CFWL_WidgetImp(properties, pOuter),
416       m_iBtnState(1),
417       m_iYear(-1),
418       m_iMonth(-1),
419       m_iDay(-1),
420       m_bLBtnDown(FALSE),
421       m_pEdit(nullptr),
422       m_pMonthCal(nullptr),
423       m_pForm(nullptr) {
424   m_rtBtn.Set(0, 0, 0, 0);
425 }
~CFWL_DateTimePickerImp()426 CFWL_DateTimePickerImp::~CFWL_DateTimePickerImp() {
427 }
GetClassName(CFX_WideString & wsClass) const428 FWL_ERR CFWL_DateTimePickerImp::GetClassName(CFX_WideString& wsClass) const {
429   wsClass = FWL_CLASS_DateTimePicker;
430   return FWL_ERR_Succeeded;
431 }
GetClassID() const432 FX_DWORD CFWL_DateTimePickerImp::GetClassID() const {
433   return FWL_CLASSHASH_DateTimePicker;
434 }
Initialize()435 FWL_ERR CFWL_DateTimePickerImp::Initialize() {
436   if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
437     return FWL_ERR_Indefinite;
438   m_pDelegate = new CFWL_DateTimePickerImpDelegate(this);
439   m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat;
440   CFWL_WidgetImpProperties propMonth;
441   propMonth.m_dwStyles = FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border;
442   propMonth.m_dwStates = FWL_WGTSTATE_Invisible;
443   propMonth.m_pDataProvider = &m_MonthCalendarDP;
444   propMonth.m_pParent = m_pInterface;
445   propMonth.m_pThemeProvider = m_pProperties->m_pThemeProvider;
446   m_pMonthCal.reset(IFWL_DateTimeCalender::Create(propMonth, m_pInterface));
447   m_pMonthCal->Initialize();
448   CFX_RectF rtMonthCal;
449   m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE);
450   rtMonthCal.Set(0, 0, rtMonthCal.width, rtMonthCal.height);
451   m_pMonthCal->SetWidgetRect(rtMonthCal);
452   CFWL_WidgetImpProperties propEdit;
453   propEdit.m_pParent = m_pInterface;
454   propEdit.m_pThemeProvider = m_pProperties->m_pThemeProvider;
455   m_pEdit.reset(IFWL_DateTimeEdit::Create(propEdit, m_pInterface));
456   m_pEdit->Initialize();
457   RegisterEventTarget(m_pMonthCal.get());
458   RegisterEventTarget(m_pEdit.get());
459   return FWL_ERR_Succeeded;
460 }
Finalize()461 FWL_ERR CFWL_DateTimePickerImp::Finalize() {
462   if (m_pEdit) {
463     m_pEdit->Finalize();
464   }
465   if (m_pMonthCal) {
466     m_pMonthCal->Finalize();
467   }
468   if (m_pForm) {
469     m_pForm->Finalize();
470   }
471   UnregisterEventTarget();
472   delete m_pDelegate;
473   m_pDelegate = nullptr;
474   return CFWL_WidgetImp::Finalize();
475 }
GetWidgetRect(CFX_RectF & rect,FX_BOOL bAutoSize)476 FWL_ERR CFWL_DateTimePickerImp::GetWidgetRect(CFX_RectF& rect,
477                                               FX_BOOL bAutoSize) {
478   if (m_pWidgetMgr->IsFormDisabled()) {
479     return DisForm_GetWidgetRect(rect, bAutoSize);
480   }
481   if (bAutoSize) {
482     rect.Set(0, 0, FWL_DTP_WIDTH, FWL_DTP_HEIGHT);
483     CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
484   } else {
485     rect = m_pProperties->m_rtWidget;
486   }
487   return FWL_ERR_Succeeded;
488 }
Update()489 FWL_ERR CFWL_DateTimePickerImp::Update() {
490   if (m_pWidgetMgr->IsFormDisabled()) {
491     return DisForm_Update();
492   }
493   if (m_iLock) {
494     return FWL_ERR_Indefinite;
495   }
496   if (!m_pProperties->m_pThemeProvider) {
497     m_pProperties->m_pThemeProvider = GetAvailableTheme();
498   }
499   m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
500   GetClientRect(m_rtClient);
501   FX_FLOAT* pFWidth =
502       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
503   if (!pFWidth)
504     return FWL_ERR_Indefinite;
505   FX_FLOAT fBtn = *pFWidth;
506   m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn - 1,
507               m_rtClient.height - 1);
508   CFX_RectF rtEdit;
509   rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
510              m_rtClient.height);
511   m_pEdit->SetWidgetRect(rtEdit);
512   ReSetEditAlignment();
513   m_pEdit->Update();
514   if (!(m_pMonthCal->GetThemeProvider())) {
515     m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
516   }
517   if (m_pProperties->m_pDataProvider) {
518     IFWL_DateTimePickerDP* pData =
519         static_cast<IFWL_DateTimePickerDP*>(m_pProperties->m_pDataProvider);
520     pData->GetToday(m_pInterface, m_MonthCalendarDP.m_iCurYear,
521                     m_MonthCalendarDP.m_iCurMonth, m_MonthCalendarDP.m_iCurDay);
522   }
523   CFX_RectF rtMonthCal;
524   m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE);
525   CFX_RectF rtPopUp;
526   rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + FWL_DTP_HEIGHT,
527               rtMonthCal.width, rtMonthCal.height);
528   m_pMonthCal->SetWidgetRect(rtPopUp);
529   m_pMonthCal->Update();
530   return FWL_ERR_Succeeded;
531 }
HitTest(FX_FLOAT fx,FX_FLOAT fy)532 FX_DWORD CFWL_DateTimePickerImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
533   if (m_pWidgetMgr->IsFormDisabled()) {
534     return DisForm_HitTest(fx, fy);
535   }
536   if (m_rtClient.Contains(fx, fy)) {
537     return FWL_WGTHITTEST_Client;
538   }
539   if (IsMonthCalendarShowed()) {
540     CFX_RectF rect;
541     m_pMonthCal->GetWidgetRect(rect);
542     if (rect.Contains(fx, fy)) {
543       return FWL_WGTHITTEST_Client;
544     }
545   }
546   return FWL_WGTHITTEST_Unknown;
547 }
DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)548 FWL_ERR CFWL_DateTimePickerImp::DrawWidget(CFX_Graphics* pGraphics,
549                                            const CFX_Matrix* pMatrix) {
550   if (!pGraphics)
551     return FWL_ERR_Indefinite;
552   if (!m_pProperties->m_pThemeProvider)
553     return FWL_ERR_Indefinite;
554   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
555   if (HasBorder()) {
556     DrawBorder(pGraphics, FWL_PART_DTP_Border, pTheme, pMatrix);
557   }
558   if (HasEdge()) {
559     DrawEdge(pGraphics, FWL_PART_DTP_Edge, pTheme, pMatrix);
560   }
561   if (!m_rtBtn.IsEmpty()) {
562     DrawDropDownButton(pGraphics, pTheme, pMatrix);
563   }
564   if (m_pWidgetMgr->IsFormDisabled()) {
565     return DisForm_DrawWidget(pGraphics, pMatrix);
566   }
567   return FWL_ERR_Succeeded;
568 }
SetThemeProvider(IFWL_ThemeProvider * pTP)569 FWL_ERR CFWL_DateTimePickerImp::SetThemeProvider(IFWL_ThemeProvider* pTP) {
570   m_pProperties->m_pThemeProvider = pTP;
571   m_pMonthCal->SetThemeProvider(pTP);
572   return FWL_ERR_Succeeded;
573 }
GetCurSel(int32_t & iYear,int32_t & iMonth,int32_t & iDay)574 FWL_ERR CFWL_DateTimePickerImp::GetCurSel(int32_t& iYear,
575                                           int32_t& iMonth,
576                                           int32_t& iDay) {
577   iYear = m_iYear;
578   iMonth = m_iMonth;
579   iDay = m_iDay;
580   return FWL_ERR_Succeeded;
581 }
SetCurSel(int32_t iYear,int32_t iMonth,int32_t iDay)582 FWL_ERR CFWL_DateTimePickerImp::SetCurSel(int32_t iYear,
583                                           int32_t iMonth,
584                                           int32_t iDay) {
585   if (iYear <= 0 || iYear >= 3000)
586     return FWL_ERR_Indefinite;
587   if (iMonth <= 0 || iMonth >= 13)
588     return FWL_ERR_Indefinite;
589   if (iDay <= 0 || iDay >= 32)
590     return FWL_ERR_Indefinite;
591   m_iYear = iYear;
592   m_iMonth = iMonth;
593   m_iDay = iDay;
594   m_pMonthCal->SetSelect(iYear, iMonth, iDay);
595   return FWL_ERR_Succeeded;
596 }
SetEditText(const CFX_WideString & wsText)597 FWL_ERR CFWL_DateTimePickerImp::SetEditText(const CFX_WideString& wsText) {
598   if (!m_pEdit)
599     return FWL_ERR_Indefinite;
600   int32_t iRet = m_pEdit->SetText(wsText);
601   Repaint(&m_rtClient);
602   CFWL_Event_DtpEditChanged ev;
603   ev.m_wsText = wsText;
604   DispatchEvent(&ev);
605   return iRet;
606 }
GetEditText(CFX_WideString & wsText,int32_t nStart,int32_t nCount) const607 FWL_ERR CFWL_DateTimePickerImp::GetEditText(CFX_WideString& wsText,
608                                             int32_t nStart,
609                                             int32_t nCount) const {
610   if (m_pEdit) {
611     return m_pEdit->GetText(wsText, nStart, nCount);
612   }
613   return FWL_ERR_Indefinite;
614 }
CanUndo()615 FX_BOOL CFWL_DateTimePickerImp::CanUndo() {
616   return m_pEdit->CanUndo();
617 }
CanRedo()618 FX_BOOL CFWL_DateTimePickerImp::CanRedo() {
619   return m_pEdit->CanRedo();
620 }
Undo()621 FX_BOOL CFWL_DateTimePickerImp::Undo() {
622   return m_pEdit->Undo();
623 }
Redo()624 FX_BOOL CFWL_DateTimePickerImp::Redo() {
625   return m_pEdit->Redo();
626 }
CanCopy()627 FX_BOOL CFWL_DateTimePickerImp::CanCopy() {
628   int32_t nCount = m_pEdit->CountSelRanges();
629   return nCount > 0;
630 }
CanCut()631 FX_BOOL CFWL_DateTimePickerImp::CanCut() {
632   if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) {
633     return FALSE;
634   }
635   int32_t nCount = m_pEdit->CountSelRanges();
636   return nCount > 0;
637 }
CanSelectAll()638 FX_BOOL CFWL_DateTimePickerImp::CanSelectAll() {
639   return m_pEdit->GetTextLength() > 0;
640 }
Copy(CFX_WideString & wsCopy)641 FX_BOOL CFWL_DateTimePickerImp::Copy(CFX_WideString& wsCopy) {
642   return m_pEdit->Copy(wsCopy);
643 }
Cut(CFX_WideString & wsCut)644 FX_BOOL CFWL_DateTimePickerImp::Cut(CFX_WideString& wsCut) {
645   return m_pEdit->Cut(wsCut);
646 }
Paste(const CFX_WideString & wsPaste)647 FX_BOOL CFWL_DateTimePickerImp::Paste(const CFX_WideString& wsPaste) {
648   return m_pEdit->Paste(wsPaste);
649 }
SelectAll()650 FX_BOOL CFWL_DateTimePickerImp::SelectAll() {
651   return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded;
652 }
Delete()653 FX_BOOL CFWL_DateTimePickerImp::Delete() {
654   return m_pEdit->ClearText() == FWL_ERR_Succeeded;
655 }
DeSelect()656 FX_BOOL CFWL_DateTimePickerImp::DeSelect() {
657   return m_pEdit->ClearSelections() == FWL_ERR_Succeeded;
658 }
GetBBox(CFX_RectF & rect)659 FWL_ERR CFWL_DateTimePickerImp::GetBBox(CFX_RectF& rect) {
660   if (m_pWidgetMgr->IsFormDisabled()) {
661     return DisForm_GetBBox(rect);
662   }
663   rect = m_pProperties->m_rtWidget;
664   if (IsMonthCalendarShowed()) {
665     CFX_RectF rtMonth;
666     m_pMonthCal->GetWidgetRect(rtMonth);
667     rtMonth.Offset(m_pProperties->m_rtWidget.left,
668                    m_pProperties->m_rtWidget.top);
669     rect.Union(rtMonth);
670   }
671   return FWL_ERR_Succeeded;
672 }
SetEditLimit(int32_t nLimit)673 FWL_ERR CFWL_DateTimePickerImp::SetEditLimit(int32_t nLimit) {
674   return m_pEdit->SetLimit(nLimit);
675 }
ModifyEditStylesEx(FX_DWORD dwStylesExAdded,FX_DWORD dwStylesExRemoved)676 FWL_ERR CFWL_DateTimePickerImp::ModifyEditStylesEx(FX_DWORD dwStylesExAdded,
677                                                    FX_DWORD dwStylesExRemoved) {
678   return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
679 }
DrawDropDownButton(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)680 void CFWL_DateTimePickerImp::DrawDropDownButton(CFX_Graphics* pGraphics,
681                                                 IFWL_ThemeProvider* pTheme,
682                                                 const CFX_Matrix* pMatrix) {
683   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_Spin) ==
684       FWL_STYLEEXT_DTP_Spin) {
685     CFWL_WidgetImpProperties prop;
686     prop.m_dwStyleExes |= FWL_STYLEEXE_SPB_Vert;
687     prop.m_pParent = m_pInterface;
688     prop.m_rtWidget = m_rtBtn;
689     IFWL_SpinButton* pSpin = IFWL_SpinButton::Create(prop, m_pInterface);
690     pSpin->Initialize();
691   } else {
692     CFWL_ThemeBackground param;
693     param.m_pWidget = m_pInterface;
694     param.m_iPart = FWL_PART_DTP_DropDownButton;
695     param.m_dwStates = m_iBtnState;
696     param.m_pGraphics = pGraphics;
697     param.m_rtPart = m_rtBtn;
698     if (pMatrix) {
699       param.m_matrix.Concat(*pMatrix);
700     }
701     pTheme->DrawBackground(&param);
702   }
703 }
FormatDateString(int32_t iYear,int32_t iMonth,int32_t iDay,CFX_WideString & wsText)704 void CFWL_DateTimePickerImp::FormatDateString(int32_t iYear,
705                                               int32_t iMonth,
706                                               int32_t iDay,
707                                               CFX_WideString& wsText) {
708   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat) ==
709       FWL_STYLEEXT_DTP_ShortDateFormat) {
710     wsText.Format(L"%d-%d-%d", iYear, iMonth, iDay);
711   } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) ==
712              FWL_STYLEEXT_DTP_LongDateFormat) {
713     wsText.Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay);
714   } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_TimeFormat) ==
715              FWL_STYLEEXT_DTP_TimeFormat) {
716   }
717 }
ShowMonthCalendar(FX_BOOL bActivate)718 void CFWL_DateTimePickerImp::ShowMonthCalendar(FX_BOOL bActivate) {
719   if (m_pWidgetMgr->IsFormDisabled()) {
720     return DisForm_ShowMonthCalendar(bActivate);
721   }
722   if (IsMonthCalendarShowed() == bActivate) {
723     return;
724   }
725   if (!m_pForm) {
726     InitProxyForm();
727   }
728   if (bActivate) {
729     CFX_RectF rtMonth;
730     m_pMonthCal->GetWidgetRect(rtMonth);
731     CFX_RectF rtAnchor;
732     rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
733                  m_pProperties->m_rtWidget.height);
734     GetPopupPos(0, rtMonth.height, rtAnchor, rtMonth);
735     m_pForm->SetWidgetRect(rtMonth);
736     rtMonth.left = rtMonth.top = 0;
737     m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
738     m_pMonthCal->SetWidgetRect(rtMonth);
739     m_pMonthCal->Update();
740     m_pForm->DoModal();
741   } else {
742     m_pForm->EndDoModal();
743   }
744 }
IsMonthCalendarShowed()745 FX_BOOL CFWL_DateTimePickerImp::IsMonthCalendarShowed() {
746   if (m_pWidgetMgr->IsFormDisabled()) {
747     return DisForm_IsMonthCalendarShowed();
748   }
749   if (!m_pForm)
750     return FALSE;
751   return !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);
752 }
ReSetEditAlignment()753 void CFWL_DateTimePickerImp::ReSetEditAlignment() {
754   if (!m_pEdit)
755     return;
756   FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;
757   FX_DWORD dwAdd = 0;
758   switch (dwStylExes & FWL_STYLEEXT_DTP_EditHAlignMask) {
759     case FWL_STYLEEXT_DTP_EditHCenter: {
760       dwAdd |= FWL_STYLEEXT_EDT_HCenter;
761       break;
762     }
763     case FWL_STYLEEXT_DTP_EditHFar: {
764       dwAdd |= FWL_STYLEEXT_EDT_HFar;
765       break;
766     }
767     default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; }
768   }
769   switch (dwStylExes & FWL_STYLEEXT_DTP_EditVAlignMask) {
770     case FWL_STYLEEXT_DTP_EditVCenter: {
771       dwAdd |= FWL_STYLEEXT_EDT_VCenter;
772       break;
773     }
774     case FWL_STYLEEXT_DTP_EditVFar: {
775       dwAdd |= FWL_STYLEEXT_EDT_VFar;
776       break;
777     }
778     default: { dwAdd |= FWL_STYLEEXT_EDT_VNear; }
779   }
780   if (dwStylExes & FWL_STYLEEXT_DTP_EditJustified) {
781     dwAdd |= FWL_STYLEEXT_EDT_Justified;
782   }
783   if (dwStylExes & FWL_STYLEEXT_DTP_EditDistributed) {
784     dwAdd |= FWL_STYLEEXT_EDT_Distributed;
785   }
786   m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
787                                      FWL_STYLEEXT_EDT_HAlignModeMask |
788                                      FWL_STYLEEXT_EDT_VAlignMask);
789 }
ProcessSelChanged(int32_t iYear,int32_t iMonth,int32_t iDay)790 void CFWL_DateTimePickerImp::ProcessSelChanged(int32_t iYear,
791                                                int32_t iMonth,
792                                                int32_t iDay) {
793   m_iYear = iYear;
794   m_iMonth = iMonth;
795   m_iDay = iDay;
796   CFX_WideString wsText;
797   FormatDateString(m_iYear, m_iMonth, m_iDay, wsText);
798   m_pEdit->SetText(wsText);
799   m_pEdit->Update();
800   Repaint(&m_rtClient);
801   CFWL_Event_DtpSelectChanged ev;
802   ev.m_pSrcTarget = m_pInterface;
803   ev.iYear = m_iYear;
804   ev.iMonth = m_iMonth;
805   ev.iDay = m_iDay;
806   DispatchEvent(&ev);
807 }
InitProxyForm()808 void CFWL_DateTimePickerImp::InitProxyForm() {
809   if (m_pForm)
810     return;
811   if (!m_pMonthCal)
812     return;
813   CFWL_WidgetImpProperties propForm;
814   propForm.m_dwStyles = FWL_WGTSTYLE_Popup;
815   propForm.m_dwStates = FWL_WGTSTATE_Invisible;
816   propForm.m_pOwner = m_pInterface;
817   m_pForm.reset(IFWL_DateTimeForm::Create(propForm, m_pMonthCal.get()));
818   m_pForm->Initialize();
819   m_pMonthCal->SetParent(m_pForm.get());
820 }
GetDataTimeEdit()821 IFWL_DateTimeEdit* CFWL_DateTimePickerImp::GetDataTimeEdit() {
822   return m_pEdit.get();
823 }
DisForm_Initialize()824 FWL_ERR CFWL_DateTimePickerImp::DisForm_Initialize() {
825   m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat;
826   DisForm_InitDateTimeCalendar();
827   DisForm_InitDateTimeEdit();
828   RegisterEventTarget(m_pMonthCal.get());
829   RegisterEventTarget(m_pEdit.get());
830   return FWL_ERR_Succeeded;
831 }
DisForm_InitDateTimeCalendar()832 void CFWL_DateTimePickerImp::DisForm_InitDateTimeCalendar() {
833   if (m_pMonthCal) {
834     return;
835   }
836   CFWL_WidgetImpProperties propMonth;
837   propMonth.m_dwStyles =
838       FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border | FWL_WGTSTYLE_EdgeSunken;
839   propMonth.m_dwStates = FWL_WGTSTATE_Invisible;
840   propMonth.m_pParent = m_pInterface;
841   propMonth.m_pDataProvider = &m_MonthCalendarDP;
842   propMonth.m_pThemeProvider = m_pProperties->m_pThemeProvider;
843   m_pMonthCal.reset(IFWL_DateTimeCalender::Create(propMonth, m_pInterface));
844   m_pMonthCal->Initialize();
845   CFX_RectF rtMonthCal;
846   m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE);
847   rtMonthCal.Set(0, 0, rtMonthCal.width, rtMonthCal.height);
848   m_pMonthCal->SetWidgetRect(rtMonthCal);
849 }
DisForm_InitDateTimeEdit()850 void CFWL_DateTimePickerImp::DisForm_InitDateTimeEdit() {
851   if (m_pEdit) {
852     return;
853   }
854   CFWL_WidgetImpProperties propEdit;
855   propEdit.m_pParent = m_pInterface;
856   propEdit.m_pThemeProvider = m_pProperties->m_pThemeProvider;
857   m_pEdit.reset(IFWL_DateTimeEdit::Create(propEdit, m_pInterface));
858   m_pEdit->Initialize();
859 }
DisForm_IsMonthCalendarShowed()860 FX_BOOL CFWL_DateTimePickerImp::DisForm_IsMonthCalendarShowed() {
861   if (!m_pMonthCal)
862     return FALSE;
863   return !(m_pMonthCal->GetStates() & FWL_WGTSTATE_Invisible);
864 }
DisForm_ShowMonthCalendar(FX_BOOL bActivate)865 void CFWL_DateTimePickerImp::DisForm_ShowMonthCalendar(FX_BOOL bActivate) {
866   FX_BOOL bShowed = IsMonthCalendarShowed();
867   if (bShowed == bActivate) {
868     return;
869   }
870   if (bActivate) {
871     CFX_RectF rtMonthCal;
872     m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE);
873     FX_FLOAT fPopupMin = rtMonthCal.height;
874     FX_FLOAT fPopupMax = rtMonthCal.height;
875     CFX_RectF rtAnchor(m_pProperties->m_rtWidget);
876     rtAnchor.width = rtMonthCal.width;
877     rtMonthCal.left = m_rtClient.left;
878     rtMonthCal.top = rtAnchor.Height();
879     GetPopupPos(fPopupMin, fPopupMax, rtAnchor, rtMonthCal);
880     m_pMonthCal->SetWidgetRect(rtMonthCal);
881     if (m_iYear > 0 && m_iMonth > 0 && m_iDay > 0) {
882       m_pMonthCal->SetSelect(m_iYear, m_iMonth, m_iDay);
883     }
884     m_pMonthCal->Update();
885   }
886   m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
887   if (bActivate) {
888     CFWL_MsgSetFocus msg;
889     msg.m_pDstTarget = m_pMonthCal.get();
890     msg.m_pSrcTarget = m_pEdit.get();
891     IFWL_WidgetDelegate* pDelegate = m_pEdit->SetDelegate(NULL);
892     pDelegate->OnProcessMessage(&msg);
893   }
894   CFX_RectF rtInvalidate, rtCal;
895   rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
896                    m_pProperties->m_rtWidget.height);
897   m_pMonthCal->GetWidgetRect(rtCal);
898   rtInvalidate.Union(rtCal);
899   rtInvalidate.Inflate(2, 2);
900   Repaint(&rtInvalidate);
901 }
DisForm_HitTest(FX_FLOAT fx,FX_FLOAT fy)902 FX_DWORD CFWL_DateTimePickerImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) {
903   CFX_RectF rect;
904   rect.Set(0, 0, m_pProperties->m_rtWidget.width,
905            m_pProperties->m_rtWidget.height);
906   if (rect.Contains(fx, fy)) {
907     return FWL_WGTHITTEST_Edit;
908   }
909   if (DisForm_IsNeedShowButton()) {
910     rect.width += m_fBtn;
911   }
912   if (rect.Contains(fx, fy)) {
913     return FWL_WGTHITTEST_Client;
914   }
915   if (IsMonthCalendarShowed()) {
916     m_pMonthCal->GetWidgetRect(rect);
917     if (rect.Contains(fx, fy)) {
918       return FWL_WGTHITTEST_Client;
919     }
920   }
921   return FWL_WGTHITTEST_Unknown;
922 }
DisForm_IsNeedShowButton()923 FX_BOOL CFWL_DateTimePickerImp::DisForm_IsNeedShowButton() {
924   FX_BOOL bFocus = m_pProperties->m_dwStates & FWL_WGTSTATE_Focused ||
925                    m_pMonthCal->GetStates() & FWL_WGTSTATE_Focused ||
926                    m_pEdit->GetStates() & FWL_WGTSTATE_Focused;
927   return bFocus;
928 }
DisForm_Update()929 FWL_ERR CFWL_DateTimePickerImp::DisForm_Update() {
930   if (m_iLock) {
931     return FWL_ERR_Indefinite;
932   }
933   if (!m_pProperties->m_pThemeProvider) {
934     m_pProperties->m_pThemeProvider = GetAvailableTheme();
935   }
936   m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
937   GetClientRect(m_rtClient);
938   m_pEdit->SetWidgetRect(m_rtClient);
939   ReSetEditAlignment();
940   m_pEdit->Update();
941   if (m_pMonthCal->GetThemeProvider() == NULL) {
942     m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
943   }
944   if (m_pProperties->m_pDataProvider) {
945     IFWL_DateTimePickerDP* pData =
946         static_cast<IFWL_DateTimePickerDP*>(m_pProperties->m_pDataProvider);
947     pData->GetToday(m_pInterface, m_MonthCalendarDP.m_iCurYear,
948                     m_MonthCalendarDP.m_iCurMonth, m_MonthCalendarDP.m_iCurDay);
949   }
950   FX_FLOAT* pWidth =
951       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
952   if (!pWidth)
953     return 0;
954   m_fBtn = *pWidth;
955   CFX_RectF rtMonthCal;
956   m_pMonthCal->GetWidgetRect(rtMonthCal, TRUE);
957   CFX_RectF rtPopUp;
958   rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + FWL_DTP_HEIGHT,
959               rtMonthCal.width, rtMonthCal.height);
960   m_pMonthCal->SetWidgetRect(rtPopUp);
961   m_pMonthCal->Update();
962   return FWL_ERR_Succeeded;
963 }
DisForm_GetWidgetRect(CFX_RectF & rect,FX_BOOL bAutoSize)964 FWL_ERR CFWL_DateTimePickerImp::DisForm_GetWidgetRect(CFX_RectF& rect,
965                                                       FX_BOOL bAutoSize) {
966   rect = m_pProperties->m_rtWidget;
967   if (DisForm_IsNeedShowButton()) {
968     rect.width += m_fBtn;
969   }
970   return FWL_ERR_Succeeded;
971 }
DisForm_GetBBox(CFX_RectF & rect)972 FWL_ERR CFWL_DateTimePickerImp::DisForm_GetBBox(CFX_RectF& rect) {
973   rect = m_pProperties->m_rtWidget;
974   if (DisForm_IsNeedShowButton()) {
975     rect.width += m_fBtn;
976   }
977   if (IsMonthCalendarShowed()) {
978     CFX_RectF rtMonth;
979     m_pMonthCal->GetWidgetRect(rtMonth);
980     rtMonth.Offset(m_pProperties->m_rtWidget.left,
981                    m_pProperties->m_rtWidget.top);
982     rect.Union(rtMonth);
983   }
984   return FWL_ERR_Succeeded;
985 }
DisForm_DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)986 FWL_ERR CFWL_DateTimePickerImp::DisForm_DrawWidget(CFX_Graphics* pGraphics,
987                                                    const CFX_Matrix* pMatrix) {
988   if (!pGraphics)
989     return FWL_ERR_Indefinite;
990   if (m_pEdit) {
991     CFX_RectF rtEdit;
992     m_pEdit->GetWidgetRect(rtEdit);
993     CFX_Matrix mt;
994     mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
995     if (pMatrix) {
996       mt.Concat(*pMatrix);
997     }
998     m_pEdit->DrawWidget(pGraphics, &mt);
999   }
1000   if (IsMonthCalendarShowed()) {
1001     CFX_RectF rtMonth;
1002     m_pMonthCal->GetWidgetRect(rtMonth);
1003     CFX_Matrix mt;
1004     mt.Set(1, 0, 0, 1, rtMonth.left, rtMonth.top);
1005     if (pMatrix) {
1006       mt.Concat(*pMatrix);
1007     }
1008     m_pMonthCal->DrawWidget(pGraphics, &mt);
1009   }
1010   return FWL_ERR_Succeeded;
1011 }
CFWL_DateTimePickerImpDelegate(CFWL_DateTimePickerImp * pOwner)1012 CFWL_DateTimePickerImpDelegate::CFWL_DateTimePickerImpDelegate(
1013     CFWL_DateTimePickerImp* pOwner)
1014     : m_pOwner(pOwner) {}
OnProcessMessage(CFWL_Message * pMessage)1015 int32_t CFWL_DateTimePickerImpDelegate::OnProcessMessage(
1016     CFWL_Message* pMessage) {
1017   if (!pMessage)
1018     return 0;
1019   FX_DWORD dwMsgCode = pMessage->GetClassID();
1020   int32_t iRet = 1;
1021   switch (dwMsgCode) {
1022     case FWL_MSGHASH_SetFocus:
1023     case FWL_MSGHASH_KillFocus: {
1024       OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
1025       break;
1026     }
1027     case FWL_MSGHASH_Mouse: {
1028       CFWL_MsgMouse* pMouse = static_cast<CFWL_MsgMouse*>(pMessage);
1029       FX_DWORD dwCmd = pMouse->m_dwCmd;
1030       switch (dwCmd) {
1031         case FWL_MSGMOUSECMD_LButtonDown: {
1032           OnLButtonDown(pMouse);
1033           break;
1034         }
1035         case FWL_MSGMOUSECMD_LButtonUp: {
1036           OnLButtonUp(pMouse);
1037           break;
1038         }
1039         case FWL_MSGMOUSECMD_MouseMove: {
1040           OnMouseMove(pMouse);
1041           break;
1042         }
1043         case FWL_MSGMOUSECMD_MouseLeave: {
1044           OnMouseLeave(pMouse);
1045           break;
1046         }
1047         default: {}
1048       }
1049       break;
1050     }
1051     default: { iRet = 0; }
1052   }
1053   if (dwMsgCode == FWL_MSGHASH_Key &&
1054       m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
1055     IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
1056     return pDelegate->OnProcessMessage(pMessage);
1057   }
1058   return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
1059 }
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)1060 FWL_ERR CFWL_DateTimePickerImpDelegate::OnDrawWidget(
1061     CFX_Graphics* pGraphics,
1062     const CFX_Matrix* pMatrix) {
1063   return m_pOwner->DrawWidget(pGraphics, pMatrix);
1064 }
OnFocusChanged(CFWL_Message * pMsg,FX_BOOL bSet)1065 void CFWL_DateTimePickerImpDelegate::OnFocusChanged(CFWL_Message* pMsg,
1066                                                     FX_BOOL bSet) {
1067   if (!pMsg)
1068     return;
1069   if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
1070     return DisForm_OnFocusChanged(pMsg, bSet);
1071   }
1072   if (bSet) {
1073     m_pOwner->m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
1074     m_pOwner->Repaint(&m_pOwner->m_rtClient);
1075   } else {
1076     m_pOwner->m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
1077     m_pOwner->Repaint(&m_pOwner->m_rtClient);
1078   }
1079   if (pMsg->m_pSrcTarget == m_pOwner->m_pMonthCal.get() &&
1080       m_pOwner->IsMonthCalendarShowed()) {
1081     m_pOwner->ShowMonthCalendar(FALSE);
1082   }
1083   m_pOwner->Repaint(&m_pOwner->m_rtClient);
1084 }
OnLButtonDown(CFWL_MsgMouse * pMsg)1085 void CFWL_DateTimePickerImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
1086   if (!pMsg)
1087     return;
1088   if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
1089     m_pOwner->SetFocus(TRUE);
1090   }
1091   if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
1092     if (m_pOwner->IsMonthCalendarShowed()) {
1093       m_pOwner->ShowMonthCalendar(FALSE);
1094       CFWL_Event_DtpCloseUp ev;
1095       m_pOwner->DispatchEvent(&ev);
1096     } else {
1097       if (!(m_pOwner->m_pProperties->m_dwStyleExes &
1098             FWL_STYLEEXT_DTP_TimeFormat)) {
1099         m_pOwner->ShowMonthCalendar(TRUE);
1100         CFWL_Event_DtpDropDown ev;
1101         m_pOwner->DispatchEvent(&ev);
1102       } else {
1103       }
1104       m_pOwner->m_bLBtnDown = TRUE;
1105       m_pOwner->Repaint(&m_pOwner->m_rtClient);
1106     }
1107   }
1108 }
OnLButtonUp(CFWL_MsgMouse * pMsg)1109 void CFWL_DateTimePickerImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
1110   if (!pMsg)
1111     return;
1112   m_pOwner->m_bLBtnDown = FALSE;
1113   if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
1114     m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Hovered;
1115   } else {
1116     m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Normal;
1117   }
1118   m_pOwner->Repaint(&m_pOwner->m_rtBtn);
1119 }
OnMouseMove(CFWL_MsgMouse * pMsg)1120 void CFWL_DateTimePickerImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
1121   if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
1122   } else {
1123     m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Normal;
1124   }
1125   m_pOwner->Repaint(&m_pOwner->m_rtBtn);
1126 }
OnMouseLeave(CFWL_MsgMouse * pMsg)1127 void CFWL_DateTimePickerImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) {
1128   if (!pMsg)
1129     return;
1130   m_pOwner->m_iBtnState = FWL_PARTSTATE_DTP_Normal;
1131   m_pOwner->Repaint(&m_pOwner->m_rtBtn);
1132 }
DisForm_OnFocusChanged(CFWL_Message * pMsg,FX_BOOL bSet)1133 void CFWL_DateTimePickerImpDelegate::DisForm_OnFocusChanged(CFWL_Message* pMsg,
1134                                                             FX_BOOL bSet) {
1135   CFX_RectF rtInvalidate(m_pOwner->m_rtBtn);
1136   if (bSet) {
1137     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
1138     if (m_pOwner->m_pEdit &&
1139         !(m_pOwner->m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)) {
1140       m_pOwner->m_rtBtn.Set(m_pOwner->m_pProperties->m_rtWidget.width, 0,
1141                             m_pOwner->m_fBtn,
1142                             m_pOwner->m_pProperties->m_rtWidget.height - 1);
1143     }
1144     rtInvalidate = m_pOwner->m_rtBtn;
1145     pMsg->m_pDstTarget = m_pOwner->m_pEdit.get();
1146     IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
1147     pDelegate->OnProcessMessage(pMsg);
1148   } else {
1149     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
1150     m_pOwner->m_rtBtn.Set(0, 0, 0, 0);
1151     if (m_pOwner->DisForm_IsMonthCalendarShowed()) {
1152       m_pOwner->ShowMonthCalendar(FALSE);
1153     }
1154     if (m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
1155       pMsg->m_pSrcTarget = m_pOwner->m_pEdit.get();
1156       IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
1157       pDelegate->OnProcessMessage(pMsg);
1158     }
1159   }
1160   rtInvalidate.Inflate(2, 2);
1161   m_pOwner->Repaint(&rtInvalidate);
1162 }
1163