Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cfwl_monthcalendar.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
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_monthcalendar.h"
8
9#include <algorithm>
10#include <memory>
11#include <utility>
12
13#include "core/fxcrt/cfx_datetime.h"
14#include "core/fxcrt/stl_util.h"
15#include "third_party/base/check.h"
16#include "third_party/base/containers/contains.h"
17#include "third_party/base/notreached.h"
18#include "xfa/fde/cfde_textout.h"
19#include "xfa/fwl/cfwl_datetimepicker.h"
20#include "xfa/fwl/cfwl_messagemouse.h"
21#include "xfa/fwl/cfwl_notedriver.h"
22#include "xfa/fwl/cfwl_themebackground.h"
23#include "xfa/fwl/cfwl_themetext.h"
24#include "xfa/fwl/ifwl_themeprovider.h"
25
26namespace {
27
28constexpr float kMonthCalHSepHeight = 1.0f;
29constexpr float kMonthCalHMargin = 3.0f;
30constexpr float kMonthCalVMargin = 2.0f;
31constexpr float kMonthCalRows = 9.0f;
32constexpr float kMonthCalColumns = 7.0f;
33constexpr float kMonthCalHeaderBtnVMargin = 7.0f;
34constexpr float kMonthCalHeaderBtnHMargin = 5.0f;
35
36WideString GetAbbreviatedDayOfWeek(int day) {
37 switch (day) {
38 case 0:
39 return L"Sun";
40 case 1:
41 return L"Mon";
42 case 2:
43 return L"Tue";
44 case 3:
45 return L"Wed";
46 case 4:
47 return L"Thu";
48 case 5:
49 return L"Fri";
50 case 6:
51 return L"Sat";
52 default:
53 NOTREACHED_NORETURN();
54 }
55}
56
57WideString GetMonth(int month) {
58 switch (month) {
59 case 0:
60 return L"January";
61 case 1:
62 return L"February";
63 case 2:
64 return L"March";
65 case 3:
66 return L"April";
67 case 4:
68 return L"May";
69 case 5:
70 return L"June";
71 case 6:
72 return L"July";
73 case 7:
74 return L"August";
75 case 8:
76 return L"September";
77 case 9:
78 return L"October";
79 case 10:
80 return L"November";
81 case 11:
82 return L"December";
83 default:
84 NOTREACHED_NORETURN();
85 }
86}
87
88} // namespace
89
90CFWL_MonthCalendar::CFWL_MonthCalendar(CFWL_App* app,
91 const Properties& properties,
92 CFWL_Widget* pOuter)
93 : CFWL_Widget(app, properties, pOuter) {}
94
95CFWL_MonthCalendar::~CFWL_MonthCalendar() = default;
96
97FWL_Type CFWL_MonthCalendar::GetClassID() const {
99}
100
101CFX_RectF CFWL_MonthCalendar::GetAutosizedWidgetRect() {
102 CFX_SizeF fs = CalcSize();
103 CFX_RectF rect(0, 0, fs.width, fs.height);
104 InflateWidgetRect(rect);
105 return rect;
106}
107
108void CFWL_MonthCalendar::Update() {
109 if (IsLocked())
110 return;
111
112 if (!m_bInitialized) {
113 InitDate();
114 m_bInitialized = true;
115 }
116 ClearDateItem();
117 ResetDateItem();
118 Layout();
119}
120
121void CFWL_MonthCalendar::DrawWidget(CFGAS_GEGraphics* pGraphics,
122 const CFX_Matrix& matrix) {
123 if (!pGraphics)
124 return;
125
126 if (HasBorder())
127 DrawBorder(pGraphics, CFWL_ThemePart::Part::kBorder, matrix);
128
129 DrawBackground(pGraphics, matrix);
130 DrawHeadBK(pGraphics, matrix);
131 DrawLButton(pGraphics, matrix);
132 DrawRButton(pGraphics, matrix);
133 DrawSeparator(pGraphics, matrix);
134 DrawDatesInBK(pGraphics, matrix);
135 DrawDatesInCircle(pGraphics, matrix);
136 DrawCaption(pGraphics, matrix);
137 DrawWeek(pGraphics, matrix);
138 DrawDatesIn(pGraphics, matrix);
139 DrawDatesOut(pGraphics, matrix);
140 DrawToday(pGraphics, matrix);
141}
142
143void CFWL_MonthCalendar::SetSelect(int32_t iYear,
144 int32_t iMonth,
145 int32_t iDay) {
146 ChangeToMonth(iYear, iMonth);
147 AddSelDay(iDay);
148}
149
150void CFWL_MonthCalendar::DrawBackground(CFGAS_GEGraphics* pGraphics,
151 const CFX_Matrix& mtMatrix) {
152 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kBackground, this,
153 pGraphics);
154 params.m_PartRect = m_ClientRect;
155 params.m_matrix = mtMatrix;
156 GetThemeProvider()->DrawBackground(params);
157}
158
159void CFWL_MonthCalendar::DrawHeadBK(CFGAS_GEGraphics* pGraphics,
160 const CFX_Matrix& mtMatrix) {
161 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kHeader, this, pGraphics);
162 params.m_PartRect = m_HeadRect;
163 params.m_matrix = mtMatrix;
164 GetThemeProvider()->DrawBackground(params);
165}
166
167void CFWL_MonthCalendar::DrawLButton(CFGAS_GEGraphics* pGraphics,
168 const CFX_Matrix& mtMatrix) {
169 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kLBtn, this, pGraphics);
170 params.m_dwStates = m_iLBtnPartStates;
171 params.m_PartRect = m_LBtnRect;
172 params.m_matrix = mtMatrix;
173 GetThemeProvider()->DrawBackground(params);
174}
175
176void CFWL_MonthCalendar::DrawRButton(CFGAS_GEGraphics* pGraphics,
177 const CFX_Matrix& mtMatrix) {
178 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kRBtn, this, pGraphics);
179 params.m_dwStates = m_iRBtnPartStates;
180 params.m_PartRect = m_RBtnRect;
181 params.m_matrix = mtMatrix;
182 GetThemeProvider()->DrawBackground(params);
183}
184
185void CFWL_MonthCalendar::DrawCaption(CFGAS_GEGraphics* pGraphics,
186 const CFX_Matrix& mtMatrix) {
187 CFWL_ThemeText textParam(CFWL_ThemePart::Part::kCaption, this, pGraphics);
188 textParam.m_wsText = GetHeadText(m_iCurYear, m_iCurMonth);
189 m_HeadSize = CalcTextSize(textParam.m_wsText, false);
190 CalcHeadSize();
191 textParam.m_PartRect = m_HeadTextRect;
192 textParam.m_dwTTOStyles.single_line_ = true;
194 textParam.m_matrix = mtMatrix;
195 GetThemeProvider()->DrawText(textParam);
196}
197
198void CFWL_MonthCalendar::DrawSeparator(CFGAS_GEGraphics* pGraphics,
199 const CFX_Matrix& mtMatrix) {
200 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kHSeparator, this,
201 pGraphics);
202 params.m_PartRect = m_HSepRect;
203 params.m_matrix = mtMatrix;
204 GetThemeProvider()->DrawBackground(params);
205}
206
207void CFWL_MonthCalendar::DrawDatesInBK(CFGAS_GEGraphics* pGraphics,
208 const CFX_Matrix& mtMatrix) {
209 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kDateInBK, this, pGraphics);
210 params.m_matrix = mtMatrix;
211
213 int32_t iCount = fxcrt::CollectionSize<int32_t>(m_DateArray);
214 for (int32_t j = 0; j < iCount; j++) {
215 DATEINFO* pDataInfo = m_DateArray[j].get();
216 if (pDataInfo->bSelected) {
217 params.m_dwStates |= CFWL_PartState::kSelected;
218 if (pDataInfo->bFlagged) {
219 params.m_dwStates |= CFWL_PartState::kFlagged;
220 }
221 } else if (j == m_iHovered - 1) {
222 params.m_dwStates |= CFWL_PartState::kHovered;
223 } else if (pDataInfo->bFlagged) {
224 params.m_dwStates = CFWL_PartState::kFlagged;
225 pTheme->DrawBackground(params);
226 }
227 params.m_PartRect = pDataInfo->rect;
228 pTheme->DrawBackground(params);
229 params.m_dwStates = CFWL_PartState::kNormal;
230 }
231}
232
233void CFWL_MonthCalendar::DrawWeek(CFGAS_GEGraphics* pGraphics,
234 const CFX_Matrix& mtMatrix) {
235 CFWL_ThemeText params(CFWL_ThemePart::Part::kWeek, this, pGraphics);
237 params.m_dwTTOStyles.single_line_ = true;
238 params.m_matrix = mtMatrix;
239
241 CFX_RectF rtDayOfWeek;
242 for (int32_t i = 0; i < 7; ++i) {
243 rtDayOfWeek = CFX_RectF(
244 m_WeekRect.left + i * (m_CellSize.width + kMonthCalHMargin * 2),
245 m_WeekRect.top, m_CellSize);
246
247 params.m_PartRect = rtDayOfWeek;
248 params.m_wsText = GetAbbreviatedDayOfWeek(i);
249 pTheme->DrawText(params);
250 }
251}
252
253void CFWL_MonthCalendar::DrawToday(CFGAS_GEGraphics* pGraphics,
254 const CFX_Matrix& mtMatrix) {
255 CFWL_ThemeText params(CFWL_ThemePart::Part::kToday, this, pGraphics);
257 params.m_wsText = GetTodayText(m_iYear, m_iMonth, m_iDay);
258 m_TodaySize = CalcTextSize(params.m_wsText, false);
259 CalcTodaySize();
260 params.m_PartRect = m_TodayRect;
261 params.m_dwTTOStyles.single_line_ = true;
262 params.m_matrix = mtMatrix;
263 GetThemeProvider()->DrawText(params);
264}
265
266void CFWL_MonthCalendar::DrawDatesIn(CFGAS_GEGraphics* pGraphics,
267 const CFX_Matrix& mtMatrix) {
268 CFWL_ThemeText params(CFWL_ThemePart::Part::kDatesIn, this, pGraphics);
270 params.m_matrix = mtMatrix;
271
273 int32_t iCount = fxcrt::CollectionSize<int32_t>(m_DateArray);
274 for (int32_t j = 0; j < iCount; j++) {
275 DATEINFO* pDataInfo = m_DateArray[j].get();
276 params.m_wsText = pDataInfo->wsDay;
277 params.m_PartRect = pDataInfo->rect;
278 params.m_dwStates = pDataInfo->AsPartStateMask();
279 if (j + 1 == m_iHovered)
280 params.m_dwStates |= CFWL_PartState::kHovered;
281
282 params.m_dwTTOStyles.single_line_ = true;
283 pTheme->DrawText(params);
284 }
285}
286
287void CFWL_MonthCalendar::DrawDatesOut(CFGAS_GEGraphics* pGraphics,
288 const CFX_Matrix& mtMatrix) {
289 CFWL_ThemeText params(CFWL_ThemePart::Part::kDatesOut, this, pGraphics);
291 params.m_matrix = mtMatrix;
292 GetThemeProvider()->DrawText(params);
293}
294
295void CFWL_MonthCalendar::DrawDatesInCircle(CFGAS_GEGraphics* pGraphics,
296 const CFX_Matrix& mtMatrix) {
297 if (m_iMonth != m_iCurMonth || m_iYear != m_iCurYear)
298 return;
299
300 if (m_iDay < 1 || m_iDay > fxcrt::CollectionSize<int32_t>(m_DateArray))
301 return;
302
303 DATEINFO* pDate = m_DateArray[m_iDay - 1].get();
304 if (!pDate)
305 return;
306
307 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kDateInCircle, this,
308 pGraphics);
309 params.m_PartRect = pDate->rect;
310 params.m_matrix = mtMatrix;
311 GetThemeProvider()->DrawBackground(params);
312}
313
314CFX_SizeF CFWL_MonthCalendar::CalcSize() {
315 float fMaxWeekW = 0.0f;
316 float fMaxWeekH = 0.0f;
317 for (int i = 0; i < 7; ++i) {
318 CFX_SizeF sz = CalcTextSize(GetAbbreviatedDayOfWeek(i), false);
319 fMaxWeekW = (fMaxWeekW >= sz.width) ? fMaxWeekW : sz.width;
320 fMaxWeekH = (fMaxWeekH >= sz.height) ? fMaxWeekH : sz.height;
321 }
322 float fDayMaxW = 0.0f;
323 float fDayMaxH = 0.0f;
324 for (int day = 10; day <= 31; day++) {
325 CFX_SizeF sz = CalcTextSize(WideString::FormatInteger(day), false);
326 fDayMaxW = (fDayMaxW >= sz.width) ? fDayMaxW : sz.width;
327 fDayMaxH = (fDayMaxH >= sz.height) ? fDayMaxH : sz.height;
328 }
329 m_CellSize.width =
330 static_cast<int>(0.5 + (fMaxWeekW >= fDayMaxW ? fMaxWeekW : fDayMaxW));
331 m_CellSize.height = fMaxWeekH >= fDayMaxH ? fMaxWeekH : fDayMaxH;
332
333 CFX_SizeF fs;
334 fs.width = m_CellSize.width * kMonthCalColumns +
335 kMonthCalHMargin * kMonthCalColumns * 2 +
336 kMonthCalHeaderBtnHMargin * 2;
337
338 float fMonthMaxW = 0.0f;
339 float fMonthMaxH = 0.0f;
340 for (int i = 0; i < 12; ++i) {
341 CFX_SizeF sz = CalcTextSize(GetMonth(i), false);
342 fMonthMaxW = (fMonthMaxW >= sz.width) ? fMonthMaxW : sz.width;
343 fMonthMaxH = (fMonthMaxH >= sz.height) ? fMonthMaxH : sz.height;
344 }
345
346 CFX_SizeF szYear = CalcTextSize(GetHeadText(m_iYear, m_iMonth), false);
347 fMonthMaxH = std::max(fMonthMaxH, szYear.height);
348 m_HeadSize = CFX_SizeF(fMonthMaxW + szYear.width, fMonthMaxH);
349 fMonthMaxW =
350 m_HeadSize.width + kMonthCalHeaderBtnHMargin * 2 + m_CellSize.width * 2;
351 fs.width = std::max(fs.width, fMonthMaxW);
352
353 m_wsToday = GetTodayText(m_iYear, m_iMonth, m_iDay);
354 m_TodaySize = CalcTextSize(m_wsToday, false);
355 m_TodaySize.height = (m_TodaySize.height >= m_CellSize.height)
356 ? m_TodaySize.height
357 : m_CellSize.height;
358 fs.height = m_CellSize.width + m_CellSize.height * (kMonthCalRows - 2) +
359 m_TodaySize.height + kMonthCalVMargin * kMonthCalRows * 2 +
360 kMonthCalHeaderBtnVMargin * 4;
361 return fs;
362}
363
364void CFWL_MonthCalendar::CalcHeadSize() {
365 float fHeadHMargin = (m_ClientRect.width - m_HeadSize.width) / 2;
366 float fHeadVMargin = (m_CellSize.width - m_HeadSize.height) / 2;
367 m_HeadTextRect = CFX_RectF(m_ClientRect.left + fHeadHMargin,
368 m_ClientRect.top + kMonthCalHeaderBtnVMargin +
369 kMonthCalVMargin + fHeadVMargin,
370 m_HeadSize);
371}
372
373void CFWL_MonthCalendar::CalcTodaySize() {
374 m_TodayFlagRect = CFX_RectF(
375 m_ClientRect.left + kMonthCalHeaderBtnHMargin + kMonthCalHMargin,
376 m_DatesRect.bottom() + kMonthCalHeaderBtnVMargin + kMonthCalVMargin,
377 m_CellSize.width, m_TodaySize.height);
378 m_TodayRect = CFX_RectF(
379 m_ClientRect.left + kMonthCalHeaderBtnHMargin + m_CellSize.width +
380 kMonthCalHMargin * 2,
381 m_DatesRect.bottom() + kMonthCalHeaderBtnVMargin + kMonthCalVMargin,
382 m_TodaySize);
383}
384
385void CFWL_MonthCalendar::Layout() {
386 m_ClientRect = GetClientRect();
387
388 m_HeadRect = CFX_RectF(
389 m_ClientRect.left + kMonthCalHeaderBtnHMargin, m_ClientRect.top,
390 m_ClientRect.width - kMonthCalHeaderBtnHMargin * 2,
391 m_CellSize.width + (kMonthCalHeaderBtnVMargin + kMonthCalVMargin) * 2);
392 m_WeekRect = CFX_RectF(m_ClientRect.left + kMonthCalHeaderBtnHMargin,
393 m_HeadRect.bottom(),
394 m_ClientRect.width - kMonthCalHeaderBtnHMargin * 2,
395 m_CellSize.height + kMonthCalVMargin * 2);
396 m_LBtnRect = CFX_RectF(m_ClientRect.left + kMonthCalHeaderBtnHMargin,
397 m_ClientRect.top + kMonthCalHeaderBtnVMargin,
398 m_CellSize.width, m_CellSize.width);
399 m_RBtnRect = CFX_RectF(m_ClientRect.left + m_ClientRect.width -
400 kMonthCalHeaderBtnHMargin - m_CellSize.width,
401 m_ClientRect.top + kMonthCalHeaderBtnVMargin,
402 m_CellSize.width, m_CellSize.width);
403 m_HSepRect = CFX_RectF(
404 m_ClientRect.left + kMonthCalHeaderBtnHMargin + kMonthCalHMargin,
405 m_WeekRect.bottom() - kMonthCalVMargin,
406 m_ClientRect.width - (kMonthCalHeaderBtnHMargin + kMonthCalHMargin) * 2,
407 kMonthCalHSepHeight);
408 m_DatesRect = CFX_RectF(m_ClientRect.left + kMonthCalHeaderBtnHMargin,
409 m_WeekRect.bottom(),
410 m_ClientRect.width - kMonthCalHeaderBtnHMargin * 2,
411 m_CellSize.height * (kMonthCalRows - 3) +
412 kMonthCalVMargin * (kMonthCalRows - 3) * 2);
413
414 CalDateItem();
415}
416
417void CFWL_MonthCalendar::CalDateItem() {
418 bool bNewWeek = false;
419 int32_t iWeekOfMonth = 0;
420 float fLeft = m_DatesRect.left;
421 float fTop = m_DatesRect.top;
422 for (const auto& pDateInfo : m_DateArray) {
423 if (bNewWeek) {
424 iWeekOfMonth++;
425 bNewWeek = false;
426 }
427 pDateInfo->rect = CFX_RectF(
428 fLeft +
429 pDateInfo->iDayOfWeek * (m_CellSize.width + (kMonthCalHMargin * 2)),
430 fTop + iWeekOfMonth * (m_CellSize.height + (kMonthCalVMargin * 2)),
431 m_CellSize.width + (kMonthCalHMargin * 2),
432 m_CellSize.height + (kMonthCalVMargin * 2));
433 if (pDateInfo->iDayOfWeek >= 6)
434 bNewWeek = true;
435 }
436}
437
438void CFWL_MonthCalendar::InitDate() {
440
441 m_iYear = now.GetYear();
442 m_iMonth = now.GetMonth();
443 m_iDay = now.GetDay();
444 m_iCurYear = m_iYear;
445 m_iCurMonth = m_iMonth;
446
447 m_wsToday = GetTodayText(m_iYear, m_iMonth, m_iDay);
448 m_wsHead = GetHeadText(m_iCurYear, m_iCurMonth);
449 m_dtMin = DATE(1500, 12, 1);
450 m_dtMax = DATE(2200, 1, 1);
451}
452
453void CFWL_MonthCalendar::ClearDateItem() {
454 m_DateArray.clear();
455}
456
457void CFWL_MonthCalendar::ResetDateItem() {
458 int32_t iDays = FX_DaysInMonth(m_iCurYear, m_iCurMonth);
459 int32_t iDayOfWeek =
460 CFX_DateTime(m_iCurYear, m_iCurMonth, 1, 0, 0, 0, 0).GetDayOfWeek();
461 for (int32_t i = 0; i < iDays; ++i, ++iDayOfWeek) {
462 if (iDayOfWeek >= 7)
463 iDayOfWeek = 0;
464
465 const bool bFlagged =
466 m_iYear == m_iCurYear && m_iMonth == m_iCurMonth && m_iDay == i + 1;
467 const bool bSelected = pdfium::Contains(m_SelDayArray, i + 1);
468 m_DateArray.push_back(
469 std::make_unique<DATEINFO>(i + 1, iDayOfWeek, bFlagged, bSelected,
470 WideString::FormatInteger(i + 1)));
471 }
472}
473
474void CFWL_MonthCalendar::NextMonth() {
475 int32_t iYear = m_iCurYear;
476 int32_t iMonth = m_iCurMonth;
477 if (iMonth >= 12) {
478 iMonth = 1;
479 iYear++;
480 } else {
481 iMonth++;
482 }
483 DATE dt(m_iCurYear, m_iCurMonth, 1);
484 if (!(dt < m_dtMax))
485 return;
486
487 m_iCurYear = iYear, m_iCurMonth = iMonth;
488 ChangeToMonth(m_iCurYear, m_iCurMonth);
489}
490
491void CFWL_MonthCalendar::PrevMonth() {
492 int32_t iYear = m_iCurYear;
493 int32_t iMonth = m_iCurMonth;
494 if (iMonth <= 1) {
495 iMonth = 12;
496 iYear--;
497 } else {
498 iMonth--;
499 }
500
501 DATE dt(m_iCurYear, m_iCurMonth, 1);
502 if (!(dt > m_dtMin))
503 return;
504
505 m_iCurYear = iYear, m_iCurMonth = iMonth;
506 ChangeToMonth(m_iCurYear, m_iCurMonth);
507}
508
509void CFWL_MonthCalendar::ChangeToMonth(int32_t iYear, int32_t iMonth) {
510 m_iCurYear = iYear;
511 m_iCurMonth = iMonth;
512 m_iHovered = -1;
513
514 ClearDateItem();
515 ResetDateItem();
516 CalDateItem();
517 m_wsHead = GetHeadText(m_iCurYear, m_iCurMonth);
518}
519
520void CFWL_MonthCalendar::RemoveSelDay() {
521 int32_t iDatesCount = fxcrt::CollectionSize<int32_t>(m_DateArray);
522 for (int32_t iSelDay : m_SelDayArray) {
523 if (iSelDay <= iDatesCount)
524 m_DateArray[iSelDay - 1]->bSelected = false;
525 }
526 m_SelDayArray.clear();
527}
528
529void CFWL_MonthCalendar::AddSelDay(int32_t iDay) {
530 DCHECK(iDay > 0);
531 if (!pdfium::Contains(m_SelDayArray, iDay))
532 return;
533
534 RemoveSelDay();
535 if (iDay <= fxcrt::CollectionSize<int32_t>(m_DateArray))
536 m_DateArray[iDay - 1]->bSelected = true;
537
538 m_SelDayArray.push_back(iDay);
539}
540
541void CFWL_MonthCalendar::JumpToToday() {
542 if (m_iYear != m_iCurYear || m_iMonth != m_iCurMonth) {
543 m_iCurYear = m_iYear;
544 m_iCurMonth = m_iMonth;
545 ChangeToMonth(m_iYear, m_iMonth);
546 AddSelDay(m_iDay);
547 return;
548 }
549
550 if (!pdfium::Contains(m_SelDayArray, m_iDay))
551 AddSelDay(m_iDay);
552}
553
554WideString CFWL_MonthCalendar::GetHeadText(int32_t iYear, int32_t iMonth) {
555 DCHECK(iMonth > 0);
556 DCHECK(iMonth < 13);
557
558 static const wchar_t* const pMonth[] = {L"January", L"February", L"March",
559 L"April", L"May", L"June",
560 L"July", L"August", L"September",
561 L"October", L"November", L"December"};
562 return WideString::Format(L"%ls, %d", pMonth[iMonth - 1], iYear);
563}
564
565WideString CFWL_MonthCalendar::GetTodayText(int32_t iYear,
566 int32_t iMonth,
567 int32_t iDay) {
568 return WideString::Format(L"Today, %d/%d/%d", iDay, iMonth, iYear);
569}
570
571int32_t CFWL_MonthCalendar::GetDayAtPoint(const CFX_PointF& point) const {
572 int i = 1; // one-based day values.
573 for (const auto& pDateInfo : m_DateArray) {
574 if (pDateInfo->rect.Contains(point))
575 return i;
576 ++i;
577 }
578 return -1;
579}
580
581CFX_RectF CFWL_MonthCalendar::GetDayRect(int32_t iDay) {
582 if (iDay <= 0 || iDay > fxcrt::CollectionSize<int32_t>(m_DateArray))
583 return CFX_RectF();
584
585 DATEINFO* pDateInfo = m_DateArray[iDay - 1].get();
586 return pDateInfo ? pDateInfo->rect : CFX_RectF();
587}
588
589void CFWL_MonthCalendar::OnProcessMessage(CFWL_Message* pMessage) {
590 switch (pMessage->GetType()) {
593 GetOuter()->GetDelegate()->OnProcessMessage(pMessage);
594 break;
596 break;
598 CFWL_MessageMouse* pMouse = static_cast<CFWL_MessageMouse*>(pMessage);
599 switch (pMouse->m_dwCmd) {
600 case CFWL_MessageMouse::MouseCommand::kLeftButtonDown:
601 OnLButtonDown(pMouse);
602 break;
603 case CFWL_MessageMouse::MouseCommand::kLeftButtonUp:
604 OnLButtonUp(pMouse);
605 break;
606 case CFWL_MessageMouse::MouseCommand::kMove:
607 OnMouseMove(pMouse);
608 break;
609 case CFWL_MessageMouse::MouseCommand::kLeave:
610 OnMouseLeave(pMouse);
611 break;
612 default:
613 break;
614 }
615 break;
616 }
617 default:
618 break;
619 }
620 // Dst target could be |this|, continue only if not destroyed by above.
621 if (pMessage->GetDstTarget())
623}
624
625void CFWL_MonthCalendar::OnDrawWidget(CFGAS_GEGraphics* pGraphics,
626 const CFX_Matrix& matrix) {
627 DrawWidget(pGraphics, matrix);
628}
629
630void CFWL_MonthCalendar::OnLButtonDown(CFWL_MessageMouse* pMsg) {
631 if (m_LBtnRect.Contains(pMsg->m_pos)) {
632 m_iLBtnPartStates = CFWL_PartState::kPressed;
633 PrevMonth();
634 RepaintRect(m_ClientRect);
635 } else if (m_RBtnRect.Contains(pMsg->m_pos)) {
636 m_iRBtnPartStates |= CFWL_PartState::kPressed;
637 NextMonth();
638 RepaintRect(m_ClientRect);
639 } else if (m_TodayRect.Contains(pMsg->m_pos)) {
640 JumpToToday();
641 RepaintRect(m_ClientRect);
642 }
643}
644
645void CFWL_MonthCalendar::OnLButtonUp(CFWL_MessageMouse* pMsg) {
646 if (m_LBtnRect.Contains(pMsg->m_pos)) {
647 m_iLBtnPartStates = CFWL_PartState::kNormal;
648 RepaintRect(m_LBtnRect);
649 return;
650 }
651 if (m_RBtnRect.Contains(pMsg->m_pos)) {
652 m_iRBtnPartStates = CFWL_PartState::kNormal;
653 RepaintRect(m_RBtnRect);
654 return;
655 }
656 if (m_TodayRect.Contains(pMsg->m_pos))
657 return;
658
659 int32_t iOldSel = 0;
660 if (!m_SelDayArray.empty())
661 iOldSel = m_SelDayArray[0];
662
663 int32_t iCurSel = GetDayAtPoint(pMsg->m_pos);
664 if (iCurSel > 0) {
665 DATEINFO* pDateInfo = m_DateArray[iCurSel - 1].get();
666 CFX_RectF rtInvalidate(pDateInfo->rect);
667 if (iOldSel > 0 && iOldSel <= fxcrt::CollectionSize<int32_t>(m_DateArray)) {
668 pDateInfo = m_DateArray[iOldSel - 1].get();
669 rtInvalidate.Union(pDateInfo->rect);
670 }
671 AddSelDay(iCurSel);
672 CFWL_DateTimePicker* pDateTime =
673 static_cast<CFWL_DateTimePicker*>(GetOuter());
674 pDateTime->ProcessSelChanged(m_iCurYear, m_iCurMonth, iCurSel);
675 pDateTime->HideMonthCalendar();
676 }
677}
678
679void CFWL_MonthCalendar::OnMouseMove(CFWL_MessageMouse* pMsg) {
680 bool bRepaint = false;
681 CFX_RectF rtInvalidate;
682 if (m_DatesRect.Contains(pMsg->m_pos)) {
683 int32_t iHover = GetDayAtPoint(pMsg->m_pos);
684 bRepaint = m_iHovered != iHover;
685 if (bRepaint) {
686 if (m_iHovered > 0)
687 rtInvalidate = GetDayRect(m_iHovered);
688 if (iHover > 0) {
689 CFX_RectF rtDay = GetDayRect(iHover);
690 if (rtInvalidate.IsEmpty())
691 rtInvalidate = rtDay;
692 else
693 rtInvalidate.Union(rtDay);
694 }
695 }
696 m_iHovered = iHover;
697 } else {
698 bRepaint = m_iHovered > 0;
699 if (bRepaint)
700 rtInvalidate = GetDayRect(m_iHovered);
701
702 m_iHovered = -1;
703 }
704 if (bRepaint && !rtInvalidate.IsEmpty())
705 RepaintRect(rtInvalidate);
706}
707
708void CFWL_MonthCalendar::OnMouseLeave(CFWL_MessageMouse* pMsg) {
709 if (m_iHovered <= 0)
710 return;
711
712 CFX_RectF rtInvalidate = GetDayRect(m_iHovered);
713 m_iHovered = -1;
714 if (!rtInvalidate.IsEmpty())
715 RepaintRect(rtInvalidate);
716}
717
718CFWL_MonthCalendar::DATEINFO::DATEINFO(int32_t day,
719 int32_t dayofweek,
720 bool bFlag,
721 bool bSelect,
722 const WideString& wsday)
723 : iDay(day),
724 iDayOfWeek(dayofweek),
725 bFlagged(bFlag),
726 bSelected(bSelect),
727 wsDay(wsday) {}
728
729CFWL_MonthCalendar::DATEINFO::~DATEINFO() = default;
730
731Mask<CFWL_PartState> CFWL_MonthCalendar::DATEINFO::AsPartStateMask() const {
732 Mask<CFWL_PartState> dwStates = CFWL_PartState::kNormal;
733 if (bFlagged)
734 dwStates |= CFWL_PartState::kFlagged;
735 if (bSelected)
736 dwStates |= CFWL_PartState::kSelected;
737 return dwStates;
738}
FDE_TextAlignment
Definition cfde_data.h:12
CFWL_PartState
FWL_Type
Definition cfwl_widget.h:46
uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth)
void ProcessSelChanged(int32_t iYear, int32_t iMonth, int32_t iDay)
const MouseCommand m_dwCmd
Type GetType() const
CFWL_Widget * GetDstTarget() const
void DrawWidget(CFGAS_GEGraphics *pGraphics, const CFX_Matrix &matrix) override
~CFWL_MonthCalendar() override
void SetSelect(int32_t iYear, int32_t iMonth, int32_t iDay)
void OnDrawWidget(CFGAS_GEGraphics *pGraphics, const CFX_Matrix &matrix) override
CFX_RectF GetAutosizedWidgetRect() override
void OnProcessMessage(CFWL_Message *pMessage) override
FWL_Type GetClassID() const override
CFX_RectF m_PartRect
CFX_Matrix m_matrix
FDE_TextStyle m_dwTTOStyles
FDE_TextAlignment m_iTTOAlign
void InflateWidgetRect(CFX_RectF &rect)
CFWL_Widget(CFWL_App *app, const Properties &properties, CFWL_Widget *pOuter)
CFWL_Widget * GetOuter() const
void OnProcessMessage(CFWL_Message *pMessage) override
bool HasBorder() const
void DrawBorder(CFGAS_GEGraphics *pGraphics, CFWL_ThemePart::Part iPartBorder, const CFX_Matrix &pMatrix)
void RepaintRect(const CFX_RectF &pRect)
IFWL_ThemeProvider * GetThemeProvider() const
virtual CFX_RectF GetClientRect()
bool IsLocked() const
int32_t GetYear() const
static CFX_DateTime Now()
uint8_t GetDay() const
int32_t GetDayOfWeek() const
CFX_DateTime(int32_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond)
uint8_t GetMonth() const
CFX_Matrix & operator=(const CFX_Matrix &other)=default
CFX_RectF(const CFX_RectF &other)=default
constexpr CFX_RectF()=default
bool IsEmpty() const
CFX_RectF & operator=(const CFX_RectF &other)=default
float bottom() const
constexpr CFX_RectF(float dst_left, float dst_top, float dst_width, float dst_height)
void Union(const CFX_RectF &rt)
virtual void DrawBackground(const CFWL_ThemeBackground &pParams)=0
virtual void DrawText(const CFWL_ThemeText &pParams)=0
static WideString Format(const wchar_t *pFormat,...)
bool single_line_
Definition cfde_data.h:29