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