Home | History | Annotate | Download | only in basewidget
      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
     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
     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
     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
     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 
     68 IFWL_DateTimePicker::IFWL_DateTimePicker() {
     69 }
     70 int32_t IFWL_DateTimePicker::CountSelRanges() {
     71   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())
     72       ->GetDataTimeEdit()
     73       ->CountSelRanges();
     74 }
     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 }
     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 }
     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 }
     92 FWL_ERR IFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) {
     93   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SetEditText(wsText);
     94 }
     95 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 }
    101 FX_BOOL IFWL_DateTimePicker::CanUndo() {
    102   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanUndo();
    103 }
    104 FX_BOOL IFWL_DateTimePicker::CanRedo() {
    105   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanRedo();
    106 }
    107 FX_BOOL IFWL_DateTimePicker::Undo() {
    108   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Undo();
    109 }
    110 FX_BOOL IFWL_DateTimePicker::Redo() {
    111   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Redo();
    112 }
    113 FX_BOOL IFWL_DateTimePicker::CanCopy() {
    114   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanCopy();
    115 }
    116 FX_BOOL IFWL_DateTimePicker::CanCut() {
    117   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanCut();
    118 }
    119 FX_BOOL IFWL_DateTimePicker::CanSelectAll() {
    120   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->CanSelectAll();
    121 }
    122 FX_BOOL IFWL_DateTimePicker::Copy(CFX_WideString& wsCopy) {
    123   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Copy(wsCopy);
    124 }
    125 FX_BOOL IFWL_DateTimePicker::Cut(CFX_WideString& wsCut) {
    126   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Cut(wsCut);
    127 }
    128 FX_BOOL IFWL_DateTimePicker::Paste(const CFX_WideString& wsPaste) {
    129   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Paste(wsPaste);
    130 }
    131 FX_BOOL IFWL_DateTimePicker::SelectAll() {
    132   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SelectAll();
    133 }
    134 FX_BOOL IFWL_DateTimePicker::Delete() {
    135   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->Delete();
    136 }
    137 FX_BOOL IFWL_DateTimePicker::DeSelect() {
    138   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->DeSelect();
    139 }
    140 FWL_ERR IFWL_DateTimePicker::GetBBox(CFX_RectF& rect) {
    141   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->GetBBox(rect);
    142 }
    143 FWL_ERR IFWL_DateTimePicker::SetEditLimit(int32_t nLimit) {
    144   return static_cast<CFWL_DateTimePickerImp*>(GetImpl())->SetEditLimit(nLimit);
    145 }
    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 }
    151 CFWL_DateTimeEdit::CFWL_DateTimeEdit(const CFWL_WidgetImpProperties& properties,
    152                                      IFWL_Widget* pOuter)
    153     : CFWL_EditImp(properties, pOuter) {}
    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 }
    160 FWL_ERR CFWL_DateTimeEdit::Finalize() {
    161   delete m_pDelegate;
    162   m_pDelegate = nullptr;
    163   return CFWL_EditImp::Finalize();
    164 }
    165 CFWL_DateTimeEditImpDelegate::CFWL_DateTimeEditImpDelegate(
    166     CFWL_DateTimeEdit* pOwner)
    167     : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) {
    168 }
    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 }
    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 }
    209 CFWL_DateTimeCalendar::CFWL_DateTimeCalendar(
    210     const CFWL_WidgetImpProperties& properties,
    211     IFWL_Widget* pOuter)
    212     : CFWL_MonthCalendarImp(properties, pOuter) {}
    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 }
    220 FWL_ERR CFWL_DateTimeCalendar::Finalize() {
    221   delete m_pDelegate;
    222   m_pDelegate = nullptr;
    223   return CFWL_MonthCalendarImp::Finalize();
    224 }
    225 CFWL_DateTimeCalendarImpDelegate::CFWL_DateTimeCalendarImpDelegate(
    226     CFWL_DateTimeCalendar* pOwner)
    227     : CFWL_MonthCalendarImpDelegate(pOwner), m_pOwner(pOwner) {
    228   m_bFlag = FALSE;
    229 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    426 CFWL_DateTimePickerImp::~CFWL_DateTimePickerImp() {
    427 }
    428 FWL_ERR CFWL_DateTimePickerImp::GetClassName(CFX_WideString& wsClass) const {
    429   wsClass = FWL_CLASS_DateTimePicker;
    430   return FWL_ERR_Succeeded;
    431 }
    432 FX_DWORD CFWL_DateTimePickerImp::GetClassID() const {
    433   return FWL_CLASSHASH_DateTimePicker;
    434 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    607 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 }
    615 FX_BOOL CFWL_DateTimePickerImp::CanUndo() {
    616   return m_pEdit->CanUndo();
    617 }
    618 FX_BOOL CFWL_DateTimePickerImp::CanRedo() {
    619   return m_pEdit->CanRedo();
    620 }
    621 FX_BOOL CFWL_DateTimePickerImp::Undo() {
    622   return m_pEdit->Undo();
    623 }
    624 FX_BOOL CFWL_DateTimePickerImp::Redo() {
    625   return m_pEdit->Redo();
    626 }
    627 FX_BOOL CFWL_DateTimePickerImp::CanCopy() {
    628   int32_t nCount = m_pEdit->CountSelRanges();
    629   return nCount > 0;
    630 }
    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 }
    638 FX_BOOL CFWL_DateTimePickerImp::CanSelectAll() {
    639   return m_pEdit->GetTextLength() > 0;
    640 }
    641 FX_BOOL CFWL_DateTimePickerImp::Copy(CFX_WideString& wsCopy) {
    642   return m_pEdit->Copy(wsCopy);
    643 }
    644 FX_BOOL CFWL_DateTimePickerImp::Cut(CFX_WideString& wsCut) {
    645   return m_pEdit->Cut(wsCut);
    646 }
    647 FX_BOOL CFWL_DateTimePickerImp::Paste(const CFX_WideString& wsPaste) {
    648   return m_pEdit->Paste(wsPaste);
    649 }
    650 FX_BOOL CFWL_DateTimePickerImp::SelectAll() {
    651   return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded;
    652 }
    653 FX_BOOL CFWL_DateTimePickerImp::Delete() {
    654   return m_pEdit->ClearText() == FWL_ERR_Succeeded;
    655 }
    656 FX_BOOL CFWL_DateTimePickerImp::DeSelect() {
    657   return m_pEdit->ClearSelections() == FWL_ERR_Succeeded;
    658 }
    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 }
    673 FWL_ERR CFWL_DateTimePickerImp::SetEditLimit(int32_t nLimit) {
    674   return m_pEdit->SetLimit(nLimit);
    675 }
    676 FWL_ERR CFWL_DateTimePickerImp::ModifyEditStylesEx(FX_DWORD dwStylesExAdded,
    677                                                    FX_DWORD dwStylesExRemoved) {
    678   return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
    679 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    821 IFWL_DateTimeEdit* CFWL_DateTimePickerImp::GetDataTimeEdit() {
    822   return m_pEdit.get();
    823 }
    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 }
    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 }
    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 }
    860 FX_BOOL CFWL_DateTimePickerImp::DisForm_IsMonthCalendarShowed() {
    861   if (!m_pMonthCal)
    862     return FALSE;
    863   return !(m_pMonthCal->GetStates() & FWL_WGTSTATE_Invisible);
    864 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
   1012 CFWL_DateTimePickerImpDelegate::CFWL_DateTimePickerImpDelegate(
   1013     CFWL_DateTimePickerImp* pOwner)
   1014     : m_pOwner(pOwner) {}
   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 }
   1060 FWL_ERR CFWL_DateTimePickerImpDelegate::OnDrawWidget(
   1061     CFX_Graphics* pGraphics,
   1062     const CFX_Matrix* pMatrix) {
   1063   return m_pOwner->DrawWidget(pGraphics, pMatrix);
   1064 }
   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 }
   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 }
   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 }
   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 }
   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 }
   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