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>
39 spaceBetweenMonth = 10,
43 weekNumbersWidth = dayWidth * 2,
44 recommendedWindowWidth = nbMonthPerRow * (dayWidth * 7 + spaceBetweenMonth) + decalX * 2
45 + weekNumbersWidth * nbMonthPerRow ,
46 recommendedWindowHeight
47 = (12 / nbMonthPerRow) * (dayWidth * 8 + spaceBetweenMonth) + decalY * 2 + 4 + dayWidth * 2,
57 void selectWholeYear();
61 void onDraw(wxPaintEvent&);
82 inline void updateSelectionDayRange();
84 void updateGridCells(
int x,
int y);
85 void updateSelectionText();
86 void updateSelectionText(YString& out, uint from, uint to);
90 wxPoint pMousePosition;
93 uint pCurrentDayYearHover;
95 uint pDayYearRangeStart;
97 uint pCurrentSelectionDayRange[2];
100 wxBitmap pCacheBackgroundImage;
110 dtHighlightRangeSimulationOut,
140 CalendarSelect& pDialog;
143 DECLARE_EVENT_TABLE()
147BEGIN_EVENT_TABLE(CalendarViewStandard, Panel)
157 textDrawOffsetY = Yuni::System::windows ? -1 : 0,
159static const wxFont font(wxFontInfo(fontSize).Family(wxFONTFAMILY_SWISS).FaceName(
"Tahoma"));
160static const wxFont fontBold(
161 wxFontInfo(fontSize).Family(wxFONTFAMILY_SWISS).Bold().FaceName(
"Tahoma"));
163CalendarViewStandard::CalendarViewStandard(wxWindow* parent, CalendarSelect& dialog) :
164 Panel(parent), calendar(GetCurrentStudy()->calendar), pDialog(dialog)
166 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
167 SetSize(recommendedWindowWidth, recommendedWindowHeight);
168 assert(parent != NULL);
170 pCurrentDayYearHover = (uint)-1;
171 pDayYearRangeStart = (uint)-1;
174 pCacheBkgReady =
false;
178 pCacheDay[i].x = 100000;
179 pCacheDay[i].type = dtNormal;
183 pCacheWeek[i].x = 100000;
184 pCacheWeek[i].type = dtInvalid;
189 updateGridCells(-1, -1);
190 Dispatcher::GUI::Post(
this, &CalendarViewStandard::updateSelectionText);
191 Dispatcher::GUI::Refresh(
this);
194void CalendarViewStandard::selectWholeYear()
196 pDialog.pHasBeenModified =
true;
199 pCurrentDayYearHover = (uint)-1;
200 pDayYearRangeStart = (uint)-1;
202 updateGridCells(-1, -1);
203 updateSelectionText();
207void CalendarViewStandard::selectNone()
209 pDialog.pHasBeenModified =
true;
212 pCurrentDayYearHover = (uint)-1;
213 pDayYearRangeStart = (uint)-1;
215 updateGridCells(-1, -1);
216 updateSelectionText();
220void CalendarViewStandard::updateGridCells(
int x,
int y)
226 auto& day = pCacheDay[d];
227 if (x >= day.x && y >= day.y && x < day.x + dayWidth && y < day.y + dayWidth)
231 pCurrentDayYearHover = d;
235 updateSelectionDayRange();
238 pCacheWeek[pCacheWeekObjectID[w]].type = dtWeekNormal;
243 auto& day = pCacheDay[d];
246 if (d == pCurrentDayYearHover)
259 pCacheWeek[pCacheWeekObjectID[week]].type = dtWeekHighlight;
261 if (d < pDayYearRangeStart)
263 for (uint wd = range.first; wd < range.end; ++wd)
264 pCacheDay[wd].type = dtWeek;
268 for (uint wd = d + 1; wd < range.end; ++wd)
269 pCacheDay[wd].type = dtWeek;
273 day.type = dtHighlight;
278 = (d >= pDayYearRangeStart)
279 ? ((d == pDayYearRangeStart) ? dtHighlight : dtHighlightRange)
284 if (pDayYearRangeStart == (uint)-1)
293 pCacheDay[i].type = dtHighlightRangeSimulationOut;
297 uint partial = count % 7;
301 pCacheDay[i].type = dtHighlightRangeSimulationOut;
307 if (pCurrentDayYearHover != (uint)-1)
310 uint count = pCurrentSelectionDayRange[1] - pCurrentSelectionDayRange[0] + 1;
313 for (uint i = pCurrentSelectionDayRange[0]; i <= pCurrentSelectionDayRange[1]; ++i)
314 pCacheDay[i].type = dtHighlightRangeSimulationOut;
318 uint partial = count % 7;
319 for (uint i = pCurrentSelectionDayRange[1] - partial + 1;
320 i <= pCurrentSelectionDayRange[1];
322 pCacheDay[i].type = dtHighlightRangeSimulationOut;
328 if (pDayYearRangeStart < calendar.maxDaysInYear && pDayYearRangeStart > 0)
332 for (uint wd = range.first; wd < pDayYearRangeStart; ++wd)
333 pCacheDay[wd].type = dtWeek;
342 pMousePosition.x = x;
343 pMousePosition.y = y;
344 if (pDayYearRangeStart == (uint)-1)
345 pCurrentDayYearHover = (uint)-1;
347 updateGridCells(x, y);
349 if (pDayYearRangeStart != (uint)-1)
350 updateSelectionText();
358 pDayYearRangeStart = pCurrentDayYearHover;
360 pCurrentDayYearHover = (uint)-1;
361 const auto& position = evt.GetPosition();
362 updateGridCells(position.x, position.y);
364 Dispatcher::GUI::Refresh(
this);
380 pDialog.pHasBeenModified =
true;
385 pDialog.pCanceled =
false;
387 Dispatcher::GUI::Close(&pDialog, 100);
391 pCurrentDayYearHover = (uint)-1;
392 pDayYearRangeStart = (uint)-1;
394 updateSelectionDayRange();
395 updateGridCells(10000, 0);
396 Dispatcher::GUI::Refresh(
this);
397 updateSelectionText();
404 wxAutoBufferedPaintDC dc(
this);
411 const wxColour bkgColor(255, 255, 255);
413 if (not pCacheBkgReady)
415 pCacheBackgroundImage.Create(recommendedWindowWidth, recommendedWindowHeight);
417 memdc.SelectObject(pCacheBackgroundImage);
419 pCacheBkgReady =
true;
422 dc.DrawBitmap(pCacheBackgroundImage, 0, 0,
false);
431 colorSet[dtNormal].text.Set(60, 60, 60);
432 colorSet[dtNormal].background.Set(255, 255, 255);
434 colorSet[dtWeekNormal].text.Set(170, 170, 170);
435 colorSet[dtWeekNormal].background.Set(255, 255, 255);
437 colorSet[dtWeekHighlight].text.Set(0, 0, 0);
438 colorSet[dtWeekHighlight].background.Set(235, 235, 235);
440 colorSet[dtHighlight].text.Set(250, 250, 250);
441 colorSet[dtHighlight].background.Set(10, 10, 10);
443 colorSet[dtHighlightRange].text.Set(230, 230, 230);
444 colorSet[dtHighlightRange].background.Set(80, 80, 80);
446 colorSet[dtHighlightRangeSimulationOut].text.Set(230, 230, 230);
447 colorSet[dtHighlightRangeSimulationOut].background.Set(200, 30, 30);
449 colorSet[dtWeek].text.Set(50, 40, 40);
450 colorSet[dtWeek].background.Set(210, 210, 215);
452 colorSet[dtSelection].text.Set(30, 30, 30);
453 colorSet[dtSelection].background.Set(157, 205, 255);
457 auto& cache = pCacheDay[day];
458 auto& colors = colorSet[cache.type];
460 dc.SetBrush(wxBrush(colors.background, wxBRUSHSTYLE_SOLID));
461 dc.SetPen(wxPen(colors.background, 1, wxPENSTYLE_SOLID));
462 dc.SetTextForeground(colors.text);
464 dc.DrawRectangle(wxRect(cache.x, cache.y, dayWidth, dayWidth));
465 dc.DrawText(cache.text, cache.textX, cache.textY);
470 auto& cache = pCacheWeek[week];
471 if (cache.type == dtInvalid)
473 auto& colors = colorSet[cache.type];
475 dc.SetBrush(wxBrush(colors.background, wxBRUSHSTYLE_SOLID));
476 dc.SetPen(wxPen(colors.background, 1, wxPENSTYLE_SOLID));
477 dc.SetTextForeground(colors.text);
479 dc.DrawRectangle(wxRect(cache.x, cache.y, weekNumbersWidth, dayWidth));
480 dc.DrawText(cache.text, cache.textX, cache.textY);
484inline void CalendarViewStandard::updateSelectionDayRange()
486 pCurrentSelectionDayRange[0] = Math::Min(pDayYearRangeStart, pCurrentDayYearHover);
487 pCurrentSelectionDayRange[1] = Math::Max(pDayYearRangeStart, pCurrentDayYearHover);
490void CalendarViewStandard::prepareGrid(wxDC& dc,
const Date::Calendar& calendar)
495 wxRect rect = GetRect();
496 const wxColour bkgColor(255, 255, 255);
499 dc.SetPen(wxPen(bkgColor, 1, wxPENSTYLE_SOLID));
500 dc.SetBrush(wxBrush(bkgColor, wxBRUSHSTYLE_SOLID));
501 dc.DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight());
504 monthRect.x = weekNumbersWidth;
506 monthRect.width = dayWidth * 7;
507 monthRect.height = dayWidth * 6 + dayWidth + borderWidth * 4;
510 wxColour dayTextColor(60, 60, 60);
511 wxColour dayTextColorOdd(100, 50, 50);
512 wxColour dayBkgColor(255, 255, 255);
513 wxColour dayUserSelectTextColor(20, 20, 20);
514 wxColour dayUserSelectBkgColor(255, 230, 230);
516 wxColour weekdaysBkgColor(250, 250, 250);
517 wxColour weekdaysTextColor(40, 40, 40);
519 wxColour monthBkgColor(89, 124, 145);
520 wxColour monthTextColor(250, 250, 250);
522 wxColour selectionBkgColor(175, 186, 209);
523 wxColour selectionTextColor(40, 40, 40);
524 wxColour selectionDayBkgColor(131, 139, 157);
525 wxColour selectionDayTextColor(250, 250, 250);
532 for (uint month = 0; month != 12; ++month)
536 if (0 == (month % nbMonthPerRow))
538 monthRect.x = weekNumbersWidth;
539 monthRect.y = maxY + dayWidth + borderWidth;
543 monthRect.x += weekNumbersWidth + monthRect.width + spaceBetweenMonth;
550 dc.SetFont(fontBold);
552 uint x = decalX + monthRect.x + wx;
553 uint y = decalY + monthRect.y + wy;
559 dc.SetPen(wxPen(monthBkgColor, 1, wxPENSTYLE_SOLID));
560 dc.SetBrush(wxBrush(monthBkgColor, wxBRUSHSTYLE_SOLID));
561 dc.DrawRectangle(wxRect(x, y, w, dayWidth));
564 auto extend = dc.GetTextExtent(text);
565 dc.SetTextForeground(monthTextColor);
567 text, x + w / 2 - extend.GetWidth() / 2, y + dayWidth / 2 - extend.GetHeight() / 2);
573 dc.SetTextForeground(weekdaysTextColor);
574 dc.SetPen(wxPen(weekdaysBkgColor, 1, wxPENSTYLE_SOLID));
575 dc.SetBrush(wxBrush(weekdaysBkgColor, wxBRUSHSTYLE_SOLID));
576 for (uint wd = 0; wd != 7; ++wd)
578 uint x = decalX + monthRect.x + wx + (wd * dayWidth);
579 uint y = decalY + monthRect.y + wy;
581 dc.DrawRectangle(wxRect(x, y, dayWidth, dayWidth));
583 text = Date::WeekdayToLShortString(wd);
584 auto extend = dc.GetTextExtent(text);
586 x + dayWidth / 2 - extend.GetWidth() / 2,
587 y + dayWidth / 2 - extend.GetHeight() / 2);
589 dc.SetPen(wxPen(monthBkgColor, 1, wxPENSTYLE_SOLID));
592 uint x = decalX + monthRect.x + wx;
593 uint y = decalY + monthRect.y + wy;
594 dc.DrawLine(x, y, x + dayWidth * 7, y);
599 uint weekNumbersX = decalX + monthRect.x + wx - weekNumbersWidth;
600 uint weekNumbersY = decalY + monthRect.y + wy;
604 wx += graphicalWeekday * dayWidth;
610 auto& cacheweek = pCacheWeek[weekIndex];
611 cacheweek.x = weekNumbersX;
612 cacheweek.y = weekNumbersY;
613 cacheweek.type = dtWeekNormal;
616 for (uint day = 0; day < daysPerMonth; ++day, ++dayYear)
618 uint x = decalX + monthRect.x + wx;
619 uint y = decalY + monthRect.y + wy;
621 if (not graphicalWeekday)
627 auto& cacheweek = pCacheWeek[weekIndex];
628 cacheweek.x = weekNumbersX;
629 cacheweek.y = weekNumbersY;
630 cacheweek.type = dtWeekNormal;
634 pCacheWeek[weekIndex].textX = dayYear;
636 auto& cacheday = pCacheDay[dayYear];
640 cacheday.text.clear();
641 cacheday.text << (day + 1);
643 auto extend = dc.GetTextExtent(cacheday.text);
644 cacheday.textX = x + dayWidth / 2 - extend.GetWidth() / 2;
645 cacheday.textY = y + dayWidth / 2 - extend.GetHeight() / 2 + textDrawOffsetY;
649 if (++graphicalWeekday >= 7)
651 graphicalWeekday = 0;
654 weekNumbersY += dayWidth;
663 pCacheWeek[++weekIndex].type = dtInvalid;
671 auto& cache = pCacheWeek[pseudoweek];
672 if (cache.type == dtInvalid)
685 auto extend = dc.GetTextExtent(cache.text);
686 cache.textX = cache.x + weekNumbersWidth - extend.GetWidth() - 6;
687 cache.textY = cache.y + dayWidth / 2 - extend.GetHeight() / 2 + textDrawOffsetY;
691void CalendarViewStandard::updateSelectionText(YString& text, uint from, uint to)
700 text << Date::WeekdayToString((
int)start.weekday);
702 text << (start.dayMonth + 1) <<
' ' << Date::MonthToString((
int)realmonth);
709 text << Date::WeekdayToString((
int)end.weekday);
711 text << (end.dayMonth + 1) <<
' ' << Date::MonthToString((
int)realmonth);
713 uint nbdays = to - from + 1;
714 if (nbdays > 1 && nbdays < 400)
716 text <<
" (" << nbdays;
720 uint nbweeks = nbdays / 7;
724 text << nbweeks <<
" weeks)";
732void CalendarViewStandard::updateSelectionText()
736 if (pDayYearRangeStart != (uint)-1)
738 text =
" Selecting ";
739 uint from = pCurrentSelectionDayRange[0];
740 uint to = pCurrentSelectionDayRange[1];
743 updateSelectionText(text, from, to);
750 if (from != (uint)-1)
754 updateSelectionText(text, from, to);
759 text =
"(no selection)";
Panel implementation.
Definition panel.h:36
static void OnMouseMoveFromExternalComponent()
Event triggered by any other component (not derived from Panel)
Definition panel.cpp:82
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:37
uint selectionDayRange[2]
Final Day range selection.
Definition calendar.h:56
bool allowQuickSelect
option: True to allow a quick selection (without clicking to a button)
Definition calendar.h:60
bool allowRangeSelection
option: True to allow range selection
Definition calendar.h:58
Definition view-standard.hxx:34
Date::Calendar & calendar
Current calendar.
Definition view-standard.hxx:77
void onDraw(wxPaintEvent &)
Event: draw the panel.
Definition view-standard.hxx:401
virtual void onMouseMoved(int x, int y)
wxEvent : onMouseMove
Definition view-standard.hxx:337
Yuni::Bind< void(const YString &)> onUpdateSelectionText
Event : update text.
Definition view-standard.hxx:79
virtual void onMouseUp(wxMouseEvent &)
Click up.
Definition view-standard.hxx:367
virtual void onMouseDown(wxMouseEvent &)
Click down.
Definition view-standard.hxx:355
void onEraseBackground(wxEraseEvent &)
UI: Erase background, empty to avoid flickering.
Definition view-standard.hxx:63