22 #include <ui/common/component/panel.h>
23 #include <wx/dcbuffer.h>
24 #include <yuni/core/math/math.h>
25 #include <yuni/core/bind.h>
27 namespace Antares::Window
37 spaceBetweenMonth = 10,
41 weekNumbersWidth = dayWidth * 2,
42 recommendedWindowWidth = nbMonthPerRow * (dayWidth * 7 + spaceBetweenMonth) + decalX * 2
43 + weekNumbersWidth * nbMonthPerRow ,
44 recommendedWindowHeight = (12 / nbMonthPerRow) * (dayWidth * 8 + spaceBetweenMonth)
45 + decalY * 2 + 4 + dayWidth * 2,
56 void selectWholeYear();
60 void onDraw(wxPaintEvent&);
83 inline void updateSelectionDayRange();
85 void updateGridCells(
int x,
int y);
86 void updateSelectionText();
87 void updateSelectionText(YString& out, uint from, uint to);
91 wxPoint pMousePosition;
94 uint pCurrentDayYearHover;
96 uint pDayYearRangeStart;
98 uint pCurrentSelectionDayRange[2];
101 wxBitmap pCacheBackgroundImage;
111 dtHighlightRangeSimulationOut,
141 CalendarSelect& pDialog;
144 DECLARE_EVENT_TABLE()
148 BEGIN_EVENT_TABLE(CalendarViewStandard, Panel)
158 textDrawOffsetY = Yuni::System::windows ? -1 : 0,
161 static const wxFont font(wxFontInfo(fontSize).Family(wxFONTFAMILY_SWISS).FaceName(
"Tahoma"));
162 static const wxFont fontBold(
163 wxFontInfo(fontSize).Family(wxFONTFAMILY_SWISS).Bold().FaceName(
"Tahoma"));
165 CalendarViewStandard::CalendarViewStandard(wxWindow* parent, CalendarSelect& dialog):
167 calendar(GetCurrentStudy()->calendar),
170 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
171 SetSize(recommendedWindowWidth, recommendedWindowHeight);
172 assert(parent != NULL);
174 pCurrentDayYearHover = (uint)-1;
175 pDayYearRangeStart = (uint)-1;
178 pCacheBkgReady =
false;
182 pCacheDay[i].x = 100000;
183 pCacheDay[i].type = dtNormal;
187 pCacheWeek[i].x = 100000;
188 pCacheWeek[i].type = dtInvalid;
193 updateGridCells(-1, -1);
194 Dispatcher::GUI::Post(
this, &CalendarViewStandard::updateSelectionText);
195 Dispatcher::GUI::Refresh(
this);
198 void CalendarViewStandard::selectWholeYear()
200 pDialog.pHasBeenModified =
true;
203 pCurrentDayYearHover = (uint)-1;
204 pDayYearRangeStart = (uint)-1;
206 updateGridCells(-1, -1);
207 updateSelectionText();
211 void CalendarViewStandard::selectNone()
213 pDialog.pHasBeenModified =
true;
216 pCurrentDayYearHover = (uint)-1;
217 pDayYearRangeStart = (uint)-1;
219 updateGridCells(-1, -1);
220 updateSelectionText();
224 void CalendarViewStandard::updateGridCells(
int x,
int y)
230 auto& day = pCacheDay[d];
231 if (x >= day.x && y >= day.y && x < day.x + dayWidth && y < day.y + dayWidth)
236 pCurrentDayYearHover = d;
241 updateSelectionDayRange();
245 pCacheWeek[pCacheWeekObjectID[w]].type = dtWeekNormal;
251 auto& day = pCacheDay[d];
254 if (d == pCurrentDayYearHover)
267 pCacheWeek[pCacheWeekObjectID[week]].type = dtWeekHighlight;
269 if (d < pDayYearRangeStart)
271 for (uint wd = range.first; wd < range.end; ++wd)
273 pCacheDay[wd].type = dtWeek;
278 for (uint wd = d + 1; wd < range.end; ++wd)
280 pCacheDay[wd].type = dtWeek;
285 day.type = dtHighlight;
289 day.type = (d >= pDayYearRangeStart)
290 ? ((d == pDayYearRangeStart) ? dtHighlight : dtHighlightRange)
296 if (pDayYearRangeStart == (uint)-1)
306 pCacheDay[i].type = dtHighlightRangeSimulationOut;
311 uint partial = count % 7;
316 pCacheDay[i].type = dtHighlightRangeSimulationOut;
323 if (pCurrentDayYearHover != (uint)-1)
326 uint count = pCurrentSelectionDayRange[1] - pCurrentSelectionDayRange[0] + 1;
329 for (uint i = pCurrentSelectionDayRange[0]; i <= pCurrentSelectionDayRange[1]; ++i)
331 pCacheDay[i].type = dtHighlightRangeSimulationOut;
336 uint partial = count % 7;
337 for (uint i = pCurrentSelectionDayRange[1] - partial + 1;
338 i <= pCurrentSelectionDayRange[1];
341 pCacheDay[i].type = dtHighlightRangeSimulationOut;
348 if (pDayYearRangeStart < calendar.maxDaysInYear && pDayYearRangeStart > 0)
352 for (uint wd = range.first; wd < pDayYearRangeStart; ++wd)
354 pCacheDay[wd].type = dtWeek;
364 pMousePosition.x = x;
365 pMousePosition.y = y;
366 if (pDayYearRangeStart == (uint)-1)
368 pCurrentDayYearHover = (uint)-1;
371 updateGridCells(x, y);
373 if (pDayYearRangeStart != (uint)-1)
375 updateSelectionText();
385 pDayYearRangeStart = pCurrentDayYearHover;
388 pCurrentDayYearHover = (uint)-1;
389 const auto& position = evt.GetPosition();
390 updateGridCells(position.x, position.y);
392 Dispatcher::GUI::Refresh(
this);
408 pDialog.pHasBeenModified =
true;
413 pDialog.pCanceled =
false;
415 Dispatcher::GUI::Close(&pDialog, 100);
419 pCurrentDayYearHover = (uint)-1;
420 pDayYearRangeStart = (uint)-1;
422 updateSelectionDayRange();
423 updateGridCells(10000, 0);
424 Dispatcher::GUI::Refresh(
this);
425 updateSelectionText();
432 wxAutoBufferedPaintDC dc(
this);
439 const wxColour bkgColor(255, 255, 255);
441 if (not pCacheBkgReady)
443 pCacheBackgroundImage.Create(recommendedWindowWidth, recommendedWindowHeight);
445 memdc.SelectObject(pCacheBackgroundImage);
447 pCacheBkgReady =
true;
450 dc.DrawBitmap(pCacheBackgroundImage, 0, 0,
false);
459 colorSet[dtNormal].text.Set(60, 60, 60);
460 colorSet[dtNormal].background.Set(255, 255, 255);
462 colorSet[dtWeekNormal].text.Set(170, 170, 170);
463 colorSet[dtWeekNormal].background.Set(255, 255, 255);
465 colorSet[dtWeekHighlight].text.Set(0, 0, 0);
466 colorSet[dtWeekHighlight].background.Set(235, 235, 235);
468 colorSet[dtHighlight].text.Set(250, 250, 250);
469 colorSet[dtHighlight].background.Set(10, 10, 10);
471 colorSet[dtHighlightRange].text.Set(230, 230, 230);
472 colorSet[dtHighlightRange].background.Set(80, 80, 80);
474 colorSet[dtHighlightRangeSimulationOut].text.Set(230, 230, 230);
475 colorSet[dtHighlightRangeSimulationOut].background.Set(200, 30, 30);
477 colorSet[dtWeek].text.Set(50, 40, 40);
478 colorSet[dtWeek].background.Set(210, 210, 215);
480 colorSet[dtSelection].text.Set(30, 30, 30);
481 colorSet[dtSelection].background.Set(157, 205, 255);
485 auto& cache = pCacheDay[day];
486 auto& colors = colorSet[cache.type];
488 dc.SetBrush(wxBrush(colors.background, wxBRUSHSTYLE_SOLID));
489 dc.SetPen(wxPen(colors.background, 1, wxPENSTYLE_SOLID));
490 dc.SetTextForeground(colors.text);
492 dc.DrawRectangle(wxRect(cache.x, cache.y, dayWidth, dayWidth));
493 dc.DrawText(cache.text, cache.textX, cache.textY);
498 auto& cache = pCacheWeek[week];
499 if (cache.type == dtInvalid)
503 auto& colors = colorSet[cache.type];
505 dc.SetBrush(wxBrush(colors.background, wxBRUSHSTYLE_SOLID));
506 dc.SetPen(wxPen(colors.background, 1, wxPENSTYLE_SOLID));
507 dc.SetTextForeground(colors.text);
509 dc.DrawRectangle(wxRect(cache.x, cache.y, weekNumbersWidth, dayWidth));
510 dc.DrawText(cache.text, cache.textX, cache.textY);
514 inline void CalendarViewStandard::updateSelectionDayRange()
516 pCurrentSelectionDayRange[0] = Math::Min(pDayYearRangeStart, pCurrentDayYearHover);
517 pCurrentSelectionDayRange[1] = Math::Max(pDayYearRangeStart, pCurrentDayYearHover);
520 void CalendarViewStandard::prepareGrid(wxDC& dc,
const Date::Calendar& calendar)
525 wxRect rect = GetRect();
526 const wxColour bkgColor(255, 255, 255);
529 dc.SetPen(wxPen(bkgColor, 1, wxPENSTYLE_SOLID));
530 dc.SetBrush(wxBrush(bkgColor, wxBRUSHSTYLE_SOLID));
531 dc.DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight());
534 monthRect.x = weekNumbersWidth;
536 monthRect.width = dayWidth * 7;
537 monthRect.height = dayWidth * 6 + dayWidth + borderWidth * 4;
540 wxColour dayTextColor(60, 60, 60);
541 wxColour dayTextColorOdd(100, 50, 50);
542 wxColour dayBkgColor(255, 255, 255);
543 wxColour dayUserSelectTextColor(20, 20, 20);
544 wxColour dayUserSelectBkgColor(255, 230, 230);
546 wxColour weekdaysBkgColor(250, 250, 250);
547 wxColour weekdaysTextColor(40, 40, 40);
549 wxColour monthBkgColor(89, 124, 145);
550 wxColour monthTextColor(250, 250, 250);
552 wxColour selectionBkgColor(175, 186, 209);
553 wxColour selectionTextColor(40, 40, 40);
554 wxColour selectionDayBkgColor(131, 139, 157);
555 wxColour selectionDayTextColor(250, 250, 250);
562 for (uint month = 0; month != 12; ++month)
566 if (0 == (month % nbMonthPerRow))
568 monthRect.x = weekNumbersWidth;
569 monthRect.y = maxY + dayWidth + borderWidth;
574 monthRect.x += weekNumbersWidth + monthRect.width + spaceBetweenMonth;
582 dc.SetFont(fontBold);
584 uint x = decalX + monthRect.x + wx;
585 uint y = decalY + monthRect.y + wy;
592 dc.SetPen(wxPen(monthBkgColor, 1, wxPENSTYLE_SOLID));
593 dc.SetBrush(wxBrush(monthBkgColor, wxBRUSHSTYLE_SOLID));
594 dc.DrawRectangle(wxRect(x, y, w, dayWidth));
597 auto extend = dc.GetTextExtent(text);
598 dc.SetTextForeground(monthTextColor);
600 x + w / 2 - extend.GetWidth() / 2,
601 y + dayWidth / 2 - extend.GetHeight() / 2);
607 dc.SetTextForeground(weekdaysTextColor);
608 dc.SetPen(wxPen(weekdaysBkgColor, 1, wxPENSTYLE_SOLID));
609 dc.SetBrush(wxBrush(weekdaysBkgColor, wxBRUSHSTYLE_SOLID));
610 for (uint wd = 0; wd != 7; ++wd)
612 uint x = decalX + monthRect.x + wx + (wd * dayWidth);
613 uint y = decalY + monthRect.y + wy;
615 dc.DrawRectangle(wxRect(x, y, dayWidth, dayWidth));
617 text = Date::WeekdayToLShortString(wd);
618 auto extend = dc.GetTextExtent(text);
620 x + dayWidth / 2 - extend.GetWidth() / 2,
621 y + dayWidth / 2 - extend.GetHeight() / 2);
623 dc.SetPen(wxPen(monthBkgColor, 1, wxPENSTYLE_SOLID));
626 uint x = decalX + monthRect.x + wx;
627 uint y = decalY + monthRect.y + wy;
628 dc.DrawLine(x, y, x + dayWidth * 7, y);
633 uint weekNumbersX = decalX + monthRect.x + wx - weekNumbersWidth;
634 uint weekNumbersY = decalY + monthRect.y + wy;
638 wx += graphicalWeekday * dayWidth;
644 auto& cacheweek = pCacheWeek[weekIndex];
645 cacheweek.x = weekNumbersX;
646 cacheweek.y = weekNumbersY;
647 cacheweek.type = dtWeekNormal;
650 for (uint day = 0; day < daysPerMonth; ++day, ++dayYear)
652 uint x = decalX + monthRect.x + wx;
653 uint y = decalY + monthRect.y + wy;
655 if (not graphicalWeekday)
661 auto& cacheweek = pCacheWeek[weekIndex];
662 cacheweek.x = weekNumbersX;
663 cacheweek.y = weekNumbersY;
664 cacheweek.type = dtWeekNormal;
668 pCacheWeek[weekIndex].textX = dayYear;
670 auto& cacheday = pCacheDay[dayYear];
674 cacheday.text.clear();
675 cacheday.text << (day + 1);
677 auto extend = dc.GetTextExtent(cacheday.text);
678 cacheday.textX = x + dayWidth / 2 - extend.GetWidth() / 2;
679 cacheday.textY = y + dayWidth / 2 - extend.GetHeight() / 2 + textDrawOffsetY;
685 if (++graphicalWeekday >= 7)
687 graphicalWeekday = 0;
690 weekNumbersY += dayWidth;
701 pCacheWeek[++weekIndex].type = dtInvalid;
709 for (uint pseudoweek = 0; pseudoweek != calendar.
maxWeeksInYear * 2; ++pseudoweek)
711 auto& cache = pCacheWeek[pseudoweek];
712 if (cache.type == dtInvalid)
720 uint week = calendar.
days[cache.textX].
week;
727 auto extend = dc.GetTextExtent(cache.text);
728 cache.textX = cache.x + weekNumbersWidth - extend.GetWidth() - 6;
729 cache.textY = cache.y + dayWidth / 2 - extend.GetHeight() / 2 + textDrawOffsetY;
733 void CalendarViewStandard::updateSelectionText(YString& text, uint from, uint to)
735 auto& start = calendar.
days[from];
744 text << Date::WeekdayToString((
int)start.weekday);
746 text << (start.dayMonth + 1) <<
' ' << Date::MonthToString((
int)realmonth);
750 auto& end = calendar.
days[to];
753 text << Date::WeekdayToString((
int)end.weekday);
755 text << (end.dayMonth + 1) <<
' ' << Date::MonthToString((
int)realmonth);
757 uint nbdays = to - from + 1;
758 if (nbdays > 1 && nbdays < 400)
760 text <<
" (" << nbdays;
764 uint nbweeks = nbdays / 7;
771 text << nbweeks <<
" weeks)";
782 void CalendarViewStandard::updateSelectionText()
786 if (pDayYearRangeStart != (uint)-1)
788 text =
" Selecting ";
789 uint from = pCurrentSelectionDayRange[0];
790 uint to = pCurrentSelectionDayRange[1];
795 updateSelectionText(text, from, to);
799 uint from = pDialog.selectionDayRange[0];
800 uint to = (pDialog.selectionDayRange[1] == (uint)-1) ? (uint)-1
801 : pDialog.selectionDayRange[1] - 1;
802 if (from != (uint)-1)
808 updateSelectionText(text, from, to);
814 text =
"(no selection)";
816 onUpdateSelectionText(text);
Panel implementation.
Definition: panel.h:34
static void OnMouseMoveFromExternalComponent()
Event triggered by any other component (not derived from Panel)
Definition: panel.cpp:90
struct Antares::Date::Calendar::@17 text
Human string representations for any time interval of our calendar.
struct Antares::Date::Calendar::@14 weeks[maxWeeksInYear]
Informations about weeks according the current calendar settings.
uint userweek
User week number.
Definition: date.h:254
@ maxDaysInYear
The maximum number of days in a year.
Definition: date.h:194
@ maxWeeksInYear
The maximum number of weeks in a year.
Definition: date.h:196
DayInterval daysYear
Days in the year.
Definition: date.h:247
struct Antares::Date::Calendar::@13 days[maxDaysInYear]
Informations about days in the year according the current.
struct Antares::Date::Calendar::@15 months[12+1]
Informations about months according the current calendar settings.
uint week
Week.
Definition: date.h:214
MonthName realmonth
Real month index.
Definition: date.h:276
ShortString12 name
Month name (January..December)
Definition: date.h:308
DayOfTheWeek firstWeekday
Very First weekday of the month.
Definition: date.h:274
Dialog Window for selecting a date range.
Definition: calendar.h:35
uint selectionDayRange[2]
Final Day range selection.
Definition: calendar.h:54
bool allowQuickSelect
option: True to allow a quick selection (without clicking to a button)
Definition: calendar.h:58
bool allowRangeSelection
option: True to allow range selection
Definition: calendar.h:56
Definition: view-standard.hxx:32
Date::Calendar & calendar
Current calendar.
Definition: view-standard.hxx:78
void onDraw(wxPaintEvent &)
Event: draw the panel.
Definition: view-standard.hxx:429
virtual void onMouseMoved(int x, int y)
wxEvent : onMouseMove
Definition: view-standard.hxx:359
Yuni::Bind< void(const YString &)> onUpdateSelectionText
Event : update text.
Definition: view-standard.hxx:80
virtual void onMouseUp(wxMouseEvent &)
Click up.
Definition: view-standard.hxx:395
virtual void onMouseDown(wxMouseEvent &)
Click down.
Definition: view-standard.hxx:381
void onEraseBackground(wxEraseEvent &)
UI: Erase background, empty to avoid flickering.
Definition: view-standard.hxx:63