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/check.h"
15#include "core/fxcrt/containers/contains.h"
16#include "core/fxcrt/notreached.h"
17#include "core/fxcrt/stl_util.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 pdfium {
27
28namespace {
29
30constexpr float kMonthCalHSepHeight = 1.0f;
31constexpr float kMonthCalHMargin = 3.0f;
32constexpr float kMonthCalVMargin = 2.0f;
33constexpr float kMonthCalRows = 9.0f;
34constexpr float kMonthCalColumns = 7.0f;
35constexpr float kMonthCalHeaderBtnVMargin = 7.0f;
36constexpr float kMonthCalHeaderBtnHMargin = 5.0f;
37
38WideString GetAbbreviatedDayOfWeek(int day) {
39 switch (day) {
40 case 0:
41 return WideString::FromASCII("Sun");
42 case 1:
43 return WideString::FromASCII("Mon");
44 case 2:
45 return WideString::FromASCII("Tue");
46 case 3:
47 return WideString::FromASCII("Wed");
48 case 4:
49 return WideString::FromASCII("Thu");
50 case 5:
51 return WideString::FromASCII("Fri");
52 case 6:
53 return WideString::FromASCII("Sat");
54 default:
56 }
57}
58
59WideString GetMonth(int month) {
60 switch (month) {
61 case 0:
62 return WideString::FromASCII("January");
63 case 1:
64 return WideString::FromASCII("February");
65 case 2:
66 return WideString::FromASCII("March");
67 case 3:
68 return WideString::FromASCII("April");
69 case 4:
70 return WideString::FromASCII("May");
71 case 5:
72 return WideString::FromASCII("June");
73 case 6:
74 return WideString::FromASCII("July");
75 case 7:
76 return WideString::FromASCII("August");
77 case 8:
78 return WideString::FromASCII("September");
79 case 9:
80 return WideString::FromASCII("October");
81 case 10:
82 return WideString::FromASCII("November");
83 case 11:
84 return WideString::FromASCII("December");
85 default:
87 }
88}
89
90} // namespace
91
92CFWL_MonthCalendar::CFWL_MonthCalendar(CFWL_App* app,
93 const Properties& properties,
94 CFWL_Widget* pOuter)
95 : CFWL_Widget(app, properties, pOuter) {}
96
97CFWL_MonthCalendar::~CFWL_MonthCalendar() = default;
98
99FWL_Type CFWL_MonthCalendar::GetClassID() const {
101}
102
103CFX_RectF CFWL_MonthCalendar::GetAutosizedWidgetRect() {
104 CFX_SizeF fs = CalcSize();
105 CFX_RectF rect(0, 0, fs.width, fs.height);
106 InflateWidgetRect(rect);
107 return rect;
108}
109
110void CFWL_MonthCalendar::Update() {
111 if (IsLocked())
112 return;
113
114 if (!m_bInitialized) {
115 InitDate();
116 m_bInitialized = true;
117 }
118 ClearDateItem();
119 ResetDateItem();
120 Layout();
121}
122
123void CFWL_MonthCalendar::DrawWidget(CFGAS_GEGraphics* pGraphics,
124 const CFX_Matrix& matrix) {
125 if (!pGraphics)
126 return;
127
128 if (HasBorder())
129 DrawBorder(pGraphics, CFWL_ThemePart::Part::kBorder, matrix);
130
131 DrawBackground(pGraphics, matrix);
132 DrawHeadBK(pGraphics, matrix);
133 DrawLButton(pGraphics, matrix);
134 DrawRButton(pGraphics, matrix);
135 DrawSeparator(pGraphics, matrix);
136 DrawDatesInBK(pGraphics, matrix);
137 DrawDatesInCircle(pGraphics, matrix);
138 DrawCaption(pGraphics, matrix);
139 DrawWeek(pGraphics, matrix);
140 DrawDatesIn(pGraphics, matrix);
141 DrawDatesOut(pGraphics, matrix);
142 DrawToday(pGraphics, matrix);
143}
144
145void CFWL_MonthCalendar::SetSelect(int32_t iYear,
146 int32_t iMonth,
147 int32_t iDay) {
148 ChangeToMonth(iYear, iMonth);
149 AddSelDay(iDay);
150}
151
152void CFWL_MonthCalendar::DrawBackground(CFGAS_GEGraphics* pGraphics,
153 const CFX_Matrix& mtMatrix) {
154 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kBackground, this,
155 pGraphics);
156 params.m_PartRect = m_ClientRect;
157 params.m_matrix = mtMatrix;
158 GetThemeProvider()->DrawBackground(params);
159}
160
161void CFWL_MonthCalendar::DrawHeadBK(CFGAS_GEGraphics* pGraphics,
162 const CFX_Matrix& mtMatrix) {
163 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kHeader, this, pGraphics);
164 params.m_PartRect = m_HeadRect;
165 params.m_matrix = mtMatrix;
166 GetThemeProvider()->DrawBackground(params);
167}
168
169void CFWL_MonthCalendar::DrawLButton(CFGAS_GEGraphics* pGraphics,
170 const CFX_Matrix& mtMatrix) {
171 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kLBtn, this, pGraphics);
172 params.m_dwStates = m_iLBtnPartStates;
173 params.m_PartRect = m_LBtnRect;
174 params.m_matrix = mtMatrix;
175 GetThemeProvider()->DrawBackground(params);
176}
177
178void CFWL_MonthCalendar::DrawRButton(CFGAS_GEGraphics* pGraphics,
179 const CFX_Matrix& mtMatrix) {
180 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kRBtn, this, pGraphics);
181 params.m_dwStates = m_iRBtnPartStates;
182 params.m_PartRect = m_RBtnRect;
183 params.m_matrix = mtMatrix;
184 GetThemeProvider()->DrawBackground(params);
185}
186
187void CFWL_MonthCalendar::DrawCaption(CFGAS_GEGraphics* pGraphics,
188 const CFX_Matrix& mtMatrix) {
189 CFWL_ThemeText textParam(CFWL_ThemePart::Part::kCaption, this, pGraphics);
190 textParam.m_wsText = GetHeadText(m_iCurYear, m_iCurMonth);
191 m_HeadSize = CalcTextSize(textParam.m_wsText, false);
192 CalcHeadSize();
193 textParam.m_PartRect = m_HeadTextRect;
194 textParam.m_dwTTOStyles.single_line_ = true;
196 textParam.m_matrix = mtMatrix;
197 GetThemeProvider()->DrawText(textParam);
198}
199
200void CFWL_MonthCalendar::DrawSeparator(CFGAS_GEGraphics* pGraphics,
201 const CFX_Matrix& mtMatrix) {
202 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kHSeparator, this,
203 pGraphics);
204 params.m_PartRect = m_HSepRect;
205 params.m_matrix = mtMatrix;
206 GetThemeProvider()->DrawBackground(params);
207}
208
209void CFWL_MonthCalendar::DrawDatesInBK(CFGAS_GEGraphics* pGraphics,
210 const CFX_Matrix& mtMatrix) {
211 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kDateInBK, this, pGraphics);
212 params.m_matrix = mtMatrix;
213
215 int32_t iCount = fxcrt::CollectionSize<int32_t>(m_DateArray);
216 for (int32_t j = 0; j < iCount; j++) {
217 DATEINFO* pDataInfo = m_DateArray[j].get();
218 if (pDataInfo->bSelected) {
219 params.m_dwStates |= CFWL_PartState::kSelected;
220 if (pDataInfo->bFlagged) {
221 params.m_dwStates |= CFWL_PartState::kFlagged;
222 }
223 } else if (j == m_iHovered - 1) {
224 params.m_dwStates |= CFWL_PartState::kHovered;
225 } else if (pDataInfo->bFlagged) {
226 params.m_dwStates = CFWL_PartState::kFlagged;
227 pTheme->DrawBackground(params);
228 }
229 params.m_PartRect = pDataInfo->rect;
230 pTheme->DrawBackground(params);
231 params.m_dwStates = CFWL_PartState::kNormal;
232 }
233}
234
235void CFWL_MonthCalendar::DrawWeek(CFGAS_GEGraphics* pGraphics,
236 const CFX_Matrix& mtMatrix) {
237 CFWL_ThemeText params(CFWL_ThemePart::Part::kWeek, this, pGraphics);
239 params.m_dwTTOStyles.single_line_ = true;
240 params.m_matrix = mtMatrix;
241
243 CFX_RectF rtDayOfWeek;
244 for (int32_t i = 0; i < 7; ++i) {
245 rtDayOfWeek = CFX_RectF(
246 m_WeekRect.left + i * (m_CellSize.width + kMonthCalHMargin * 2),
247 m_WeekRect.top, m_CellSize);
248
249 params.m_PartRect = rtDayOfWeek;
250 params.m_wsText = GetAbbreviatedDayOfWeek(i);
251 pTheme->DrawText(params);
252 }
253}
254
255void CFWL_MonthCalendar::DrawToday(CFGAS_GEGraphics* pGraphics,
256 const CFX_Matrix& mtMatrix) {
257 CFWL_ThemeText params(CFWL_ThemePart::Part::kToday, this, pGraphics);
259 params.m_wsText = GetTodayText(m_iYear, m_iMonth, m_iDay);
260 m_TodaySize = CalcTextSize(params.m_wsText, false);
261 CalcTodaySize();
262 params.m_PartRect = m_TodayRect;
263 params.m_dwTTOStyles.single_line_ = true;
264 params.m_matrix = mtMatrix;
265 GetThemeProvider()->DrawText(params);
266}
267
268void CFWL_MonthCalendar::DrawDatesIn(CFGAS_GEGraphics* pGraphics,
269 const CFX_Matrix& mtMatrix) {
270 CFWL_ThemeText params(CFWL_ThemePart::Part::kDatesIn, this, pGraphics);
272 params.m_matrix = mtMatrix;
273
275 int32_t iCount = fxcrt::CollectionSize<int32_t>(m_DateArray);
276 for (int32_t j = 0; j < iCount; j++) {
277 DATEINFO* pDataInfo = m_DateArray[j].get();
278 params.m_wsText = pDataInfo->wsDay;
279 params.m_PartRect = pDataInfo->rect;
280 params.m_dwStates = pDataInfo->AsPartStateMask();
281 if (j + 1 == m_iHovered)
282 params.m_dwStates |= CFWL_PartState::kHovered;
283
284 params.m_dwTTOStyles.single_line_ = true;
285 pTheme->DrawText(params);
286 }
287}
288
289void CFWL_MonthCalendar::DrawDatesOut(CFGAS_GEGraphics* pGraphics,
290 const CFX_Matrix& mtMatrix) {
291 CFWL_ThemeText params(CFWL_ThemePart::Part::kDatesOut, this, pGraphics);
293 params.m_matrix = mtMatrix;
294 GetThemeProvider()->DrawText(params);
295}
296
297void CFWL_MonthCalendar::DrawDatesInCircle(CFGAS_GEGraphics* pGraphics,
298 const CFX_Matrix& mtMatrix) {
299 if (m_iMonth != m_iCurMonth || m_iYear != m_iCurYear)
300 return;
301
302 if (m_iDay < 1 || m_iDay > fxcrt::CollectionSize<int32_t>(m_DateArray))
303 return;
304
305 DATEINFO* pDate = m_DateArray[m_iDay - 1].get();
306 if (!pDate)
307 return;
308
309 CFWL_ThemeBackground params(CFWL_ThemePart::Part::kDateInCircle, this,
310 pGraphics);
311 params.m_PartRect = pDate->rect;
312 params.m_matrix = mtMatrix;
313 GetThemeProvider()->DrawBackground(params);
314}
315
316CFX_SizeF CFWL_MonthCalendar::CalcSize() {
317 float fMaxWeekW = 0.0f;
318 float fMaxWeekH = 0.0f;
319 for (int i = 0; i < 7; ++i) {
320 CFX_SizeF sz = CalcTextSize(GetAbbreviatedDayOfWeek(i), false);
321 fMaxWeekW = (fMaxWeekW >= sz.width) ? fMaxWeekW : sz.width;
322 fMaxWeekH = (fMaxWeekH >= sz.height) ? fMaxWeekH : sz.height;
323 }
324 float fDayMaxW = 0.0f;
325 float fDayMaxH = 0.0f;
326 for (int day = 10; day <= 31; day++) {
327 CFX_SizeF sz = CalcTextSize(WideString::FormatInteger(day), false);
328 fDayMaxW = (fDayMaxW >= sz.width) ? fDayMaxW : sz.width;
329 fDayMaxH = (fDayMaxH >= sz.height) ? fDayMaxH : sz.height;
330 }
331 m_CellSize.width =
332 static_cast<int>(0.5 + (fMaxWeekW >= fDayMaxW ? fMaxWeekW : fDayMaxW));
333 m_CellSize.height = fMaxWeekH >= fDayMaxH ? fMaxWeekH : fDayMaxH;
334
335 CFX_SizeF fs;
336 fs.width = m_CellSize.width * kMonthCalColumns +
337 kMonthCalHMargin * kMonthCalColumns * 2 +
338 kMonthCalHeaderBtnHMargin * 2;
339
340 float fMonthMaxW = 0.0f;
341 float fMonthMaxH = 0.0f;
342 for (int i = 0; i < 12; ++i) {
343 CFX_SizeF sz = CalcTextSize(GetMonth(i), false);
344 fMonthMaxW = (fMonthMaxW >= sz.width) ? fMonthMaxW : sz.width;
345 fMonthMaxH = (fMonthMaxH >= sz.height) ? fMonthMaxH : sz.height;
346 }
347
348 CFX_SizeF szYear = CalcTextSize(GetHeadText(m_iYear, m_iMonth), false);
349 fMonthMaxH = std::max(fMonthMaxH, szYear.height);
350 m_HeadSize = CFX_SizeF(fMonthMaxW + szYear.width, fMonthMaxH);
351 fMonthMaxW =
352 m_HeadSize.width + kMonthCalHeaderBtnHMargin * 2 + m_CellSize.width * 2;
353 fs.width = std::max(fs.width, fMonthMaxW);
354
355 m_wsToday = GetTodayText(m_iYear, m_iMonth, m_iDay);
356 m_TodaySize = CalcTextSize(m_wsToday, false);
357 m_TodaySize.height = (m_TodaySize.height >= m_CellSize.height)
358 ? m_TodaySize.height
359 : m_CellSize.height;
360 fs.height = m_CellSize.width + m_CellSize.height * (kMonthCalRows - 2) +
361 m_TodaySize.height + kMonthCalVMargin * kMonthCalRows * 2 +
362 kMonthCalHeaderBtnVMargin * 4;
363 return fs;
364}
365
366void CFWL_MonthCalendar::CalcHeadSize() {
367 float fHeadHMargin = (m_ClientRect.width - m_HeadSize.width) / 2;
368 float fHeadVMargin = (m_CellSize.width - m_HeadSize.height) / 2;
369 m_HeadTextRect = CFX_RectF(m_ClientRect.left + fHeadHMargin,
370 m_ClientRect.top + kMonthCalHeaderBtnVMargin +
371 kMonthCalVMargin + fHeadVMargin,
372 m_HeadSize);
373}
374
375void CFWL_MonthCalendar::CalcTodaySize() {
376 m_TodayFlagRect = CFX_RectF(
377 m_ClientRect.left + kMonthCalHeaderBtnHMargin + kMonthCalHMargin,
378 m_DatesRect.bottom() + kMonthCalHeaderBtnVMargin + kMonthCalVMargin,
379 m_CellSize.width, m_TodaySize.height);
380 m_TodayRect = CFX_RectF(
381 m_ClientRect.left + kMonthCalHeaderBtnHMargin + m_CellSize.width +
382 kMonthCalHMargin * 2,
383 m_DatesRect.bottom() + kMonthCalHeaderBtnVMargin + kMonthCalVMargin,
384 m_TodaySize);
385}
386
387void CFWL_MonthCalendar::Layout() {
388 m_ClientRect = GetClientRect();
389
390 m_HeadRect = CFX_RectF(
391 m_ClientRect.left + kMonthCalHeaderBtnHMargin, m_ClientRect.top,
392 m_ClientRect.width - kMonthCalHeaderBtnHMargin * 2,
393 m_CellSize.width + (kMonthCalHeaderBtnVMargin + kMonthCalVMargin) * 2);
394 m_WeekRect = CFX_RectF(m_ClientRect.left + kMonthCalHeaderBtnHMargin,
395 m_HeadRect.bottom(),
396 m_ClientRect.width - kMonthCalHeaderBtnHMargin * 2,
397 m_CellSize.height + kMonthCalVMargin * 2);
398 m_LBtnRect = CFX_RectF(m_ClientRect.left + kMonthCalHeaderBtnHMargin,
399 m_ClientRect.top + kMonthCalHeaderBtnVMargin,
400 m_CellSize.width, m_CellSize.width);
401 m_RBtnRect = CFX_RectF(m_ClientRect.left + m_ClientRect.width -
402 kMonthCalHeaderBtnHMargin - m_CellSize.width,
403 m_ClientRect.top + kMonthCalHeaderBtnVMargin,
404 m_CellSize.width, m_CellSize.width);
405 m_HSepRect = CFX_RectF(
406 m_ClientRect.left + kMonthCalHeaderBtnHMargin + kMonthCalHMargin,
407 m_WeekRect.bottom() - kMonthCalVMargin,
408 m_ClientRect.width - (kMonthCalHeaderBtnHMargin + kMonthCalHMargin) * 2,
409 kMonthCalHSepHeight);
410 m_DatesRect = CFX_RectF(m_ClientRect.left + kMonthCalHeaderBtnHMargin,
411 m_WeekRect.bottom(),
412 m_ClientRect.width - kMonthCalHeaderBtnHMargin * 2,
413 m_CellSize.height * (kMonthCalRows - 3) +
414 kMonthCalVMargin * (kMonthCalRows - 3) * 2);
415
416 CalDateItem();
417}
418
419void CFWL_MonthCalendar::CalDateItem() {
420 bool bNewWeek = false;
421 int32_t iWeekOfMonth = 0;
422 float fLeft = m_DatesRect.left;
423 float fTop = m_DatesRect.top;
424 for (const auto& pDateInfo : m_DateArray) {
425 if (bNewWeek) {
426 iWeekOfMonth++;
427 bNewWeek = false;
428 }
429 pDateInfo->rect = CFX_RectF(
430 fLeft +
431 pDateInfo->iDayOfWeek * (m_CellSize.width + (kMonthCalHMargin * 2)),
432 fTop + iWeekOfMonth * (m_CellSize.height + (kMonthCalVMargin * 2)),
433 m_CellSize.width + (kMonthCalHMargin * 2),
434 m_CellSize.height + (kMonthCalVMargin * 2));
435 if (pDateInfo->iDayOfWeek >= 6)
436 bNewWeek = true;
437 }
438}
439
440void CFWL_MonthCalendar::InitDate() {
442
443 m_iYear = now.GetYear();
444 m_iMonth = now.GetMonth();
445 m_iDay = now.GetDay();
446 m_iCurYear = m_iYear;
447 m_iCurMonth = m_iMonth;
448
449 m_wsToday = GetTodayText(m_iYear, m_iMonth, m_iDay);
450 m_wsHead = GetHeadText(m_iCurYear, m_iCurMonth);
451 m_dtMin = DATE(1500, 12, 1);
452 m_dtMax = DATE(2200, 1, 1);
453}
454
455void CFWL_MonthCalendar::ClearDateItem() {
456 m_DateArray.clear();
457}
458
459void CFWL_MonthCalendar::ResetDateItem() {
460 int32_t iDays = FX_DaysInMonth(m_iCurYear, m_iCurMonth);
461 int32_t iDayOfWeek =
462 CFX_DateTime(m_iCurYear, m_iCurMonth, 1, 0, 0, 0, 0).GetDayOfWeek();
463 for (int32_t i = 0; i < iDays; ++i, ++iDayOfWeek) {
464 if (iDayOfWeek >= 7)
465 iDayOfWeek = 0;
466
467 const bool bFlagged =
468 m_iYear == m_iCurYear && m_iMonth == m_iCurMonth && m_iDay == i + 1;
469 const bool bSelected = Contains(m_SelDayArray, i + 1);
470 m_DateArray.push_back(
471 std::make_unique<DATEINFO>(i + 1, iDayOfWeek, bFlagged, bSelected,
472 WideString::FormatInteger(i + 1)));
473 }
474}
475
476void CFWL_MonthCalendar::NextMonth() {
477 int32_t iYear = m_iCurYear;
478 int32_t iMonth = m_iCurMonth;
479 if (iMonth >= 12) {
480 iMonth = 1;
481 iYear++;
482 } else {
483 iMonth++;
484 }
485 DATE dt(m_iCurYear, m_iCurMonth, 1);
486 if (!(dt < m_dtMax))
487 return;
488
489 m_iCurYear = iYear, m_iCurMonth = iMonth;
490 ChangeToMonth(m_iCurYear, m_iCurMonth);
491}
492
493void CFWL_MonthCalendar::PrevMonth() {
494 int32_t iYear = m_iCurYear;
495 int32_t iMonth = m_iCurMonth;
496 if (iMonth <= 1) {
497 iMonth = 12;
498 iYear--;
499 } else {
500 iMonth--;
501 }
502
503 DATE dt(m_iCurYear, m_iCurMonth, 1);
504 if (!(dt > m_dtMin))
505 return;
506
507 m_iCurYear = iYear, m_iCurMonth = iMonth;
508 ChangeToMonth(m_iCurYear, m_iCurMonth);
509}
510
511void CFWL_MonthCalendar::ChangeToMonth(int32_t iYear, int32_t iMonth) {
512 m_iCurYear = iYear;
513 m_iCurMonth = iMonth;
514 m_iHovered = -1;
515
516 ClearDateItem();
517 ResetDateItem();
518 CalDateItem();
519 m_wsHead = GetHeadText(m_iCurYear, m_iCurMonth);
520}
521
522void CFWL_MonthCalendar::RemoveSelDay() {
523 int32_t iDatesCount = fxcrt::CollectionSize<int32_t>(m_DateArray);
524 for (int32_t iSelDay : m_SelDayArray) {
525 if (iSelDay <= iDatesCount)
526 m_DateArray[iSelDay - 1]->bSelected = false;
527 }
528 m_SelDayArray.clear();
529}
530
531void CFWL_MonthCalendar::AddSelDay(int32_t iDay) {
532 DCHECK(iDay > 0);
533 if (!Contains(m_SelDayArray, iDay)) {
534 return;
535 }
536
537 RemoveSelDay();
538 if (iDay <= fxcrt::CollectionSize<int32_t>(m_DateArray))
539 m_DateArray[iDay - 1]->bSelected = true;
540
541 m_SelDayArray.push_back(iDay);
542}
543
544void CFWL_MonthCalendar::JumpToToday() {
545 if (m_iYear != m_iCurYear || m_iMonth != m_iCurMonth) {
546 m_iCurYear = m_iYear;
547 m_iCurMonth = m_iMonth;
548 ChangeToMonth(m_iYear, m_iMonth);
549 AddSelDay(m_iDay);
550 return;
551 }
552
553 if (!Contains(m_SelDayArray, m_iDay)) {
554 AddSelDay(m_iDay);
555 }
556}
557
558WideString CFWL_MonthCalendar::GetHeadText(int32_t iYear, int32_t iMonth) {
559 static const std::array<const wchar_t*, 12> pMonth = {
560 {L"January", L"February", L"March", L"April", L"May", L"June", L"July",
561 L"August", L"September", 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}
739
740} // namespace pdfium
uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth)
#define DCHECK
Definition check.h:33
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)
static WideString Format(const wchar_t *pFormat,...)
static WideString FromASCII(ByteStringView str)
void ProcessSelChanged(int32_t iYear, int32_t iMonth, int32_t iDay)
Type GetType() const
CFWL_Widget * GetDstTarget() const
void SetSelect(int32_t iYear, int32_t iMonth, int32_t iDay)
FWL_Type GetClassID() const override
void DrawWidget(CFGAS_GEGraphics *pGraphics, const CFX_Matrix &matrix) override
void OnDrawWidget(CFGAS_GEGraphics *pGraphics, const CFX_Matrix &matrix) override
void OnProcessMessage(CFWL_Message *pMessage) override
CFX_RectF GetAutosizedWidgetRect() override
FDE_TextStyle m_dwTTOStyles
FDE_TextAlignment m_iTTOAlign
void OnProcessMessage(CFWL_Message *pMessage) override
void RepaintRect(const CFX_RectF &pRect)
bool HasBorder() const
CFWL_Widget * GetOuter() const
CFWL_Widget(CFWL_App *app, const Properties &properties, CFWL_Widget *pOuter)
void DrawBorder(CFGAS_GEGraphics *pGraphics, CFWL_ThemePart::Part iPartBorder, const CFX_Matrix &pMatrix)
virtual CFX_RectF GetClientRect()
IFWL_ThemeProvider * GetThemeProvider() const
bool IsLocked() const
void InflateWidgetRect(CFX_RectF &rect)
virtual void DrawText(const CFWL_ThemeText &pParams)=0
virtual void DrawBackground(const CFWL_ThemeBackground &pParams)=0
CFX_PTemplate< float > CFX_PointF
CFX_STemplate< float > CFX_SizeF
FDE_TextAlignment
Definition cfde_data.h:14
#define NOTREACHED_NORETURN()
Definition notreached.h:22
fxcrt::WideString WideString
Definition widestring.h:207