Antares Simulator
Power System Simulator
view-standard.hxx
1 /*
2  * Copyright 2007-2025, RTE (https://www.rte-france.com)
3  * See AUTHORS.txt
4  * SPDX-License-Identifier: MPL-2.0
5  * This file is part of Antares-Simulator,
6  * Adequacy and Performance assessment for interconnected energy networks.
7  *
8  * Antares_Simulator is free software: you can redistribute it and/or modify
9  * it under the terms of the Mozilla Public Licence 2.0 as published by
10  * the Mozilla Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * Antares_Simulator is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * Mozilla Public Licence 2.0 for more details.
17  *
18  * You should have received a copy of the Mozilla Public Licence 2.0
19  * along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
20  */
21 
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>
26 
27 namespace Antares::Window
28 {
29 class CalendarSelect;
30 
32 {
33 public:
34  enum
35  {
36  nbMonthPerRow = 4,
37  spaceBetweenMonth = 10,
38  dayWidth = 18,
39  decalX = 10,
40  decalY = 10,
41  weekNumbersWidth = dayWidth * 2,
42  recommendedWindowWidth = nbMonthPerRow * (dayWidth * 7 + spaceBetweenMonth) + decalX * 2
43  + weekNumbersWidth * nbMonthPerRow /* week number*/,
44  recommendedWindowHeight = (12 / nbMonthPerRow) * (dayWidth * 8 + spaceBetweenMonth)
45  + decalY * 2 + 4 + dayWidth * 2,
46  borderWidth = 4
47  };
48 
49 public:
50  CalendarViewStandard(wxWindow* parent, CalendarSelect& dialog);
51 
52  virtual ~CalendarViewStandard()
53  {
54  }
55 
56  void selectWholeYear();
57  void selectNone();
58 
60  void onDraw(wxPaintEvent&);
61 
63  void onEraseBackground(wxEraseEvent&)
64  {
65  }
66 
68  virtual void onMouseMoved(int x, int y);
69 
71  virtual void onMouseDown(wxMouseEvent&);
72 
74  virtual void onMouseUp(wxMouseEvent&);
75 
76 public:
80  Yuni::Bind<void(const YString&)> onUpdateSelectionText;
81 
82 private:
83  inline void updateSelectionDayRange();
84  void prepareGrid(wxDC& dc, const Date::Calendar& calendar);
85  void updateGridCells(int x, int y);
86  void updateSelectionText();
87  void updateSelectionText(YString& out, uint from, uint to);
88 
89 private:
91  wxPoint pMousePosition;
92 
94  uint pCurrentDayYearHover;
96  uint pDayYearRangeStart;
98  uint pCurrentSelectionDayRange[2];
99 
101  wxBitmap pCacheBackgroundImage;
103  bool pCacheBkgReady;
104 
105  enum DayType
106  {
107  dtInvalid,
108  dtNormal,
109  dtHighlight,
110  dtHighlightRange,
111  dtHighlightRangeSimulationOut,
112  dtSelection,
113  dtWeek,
114  dtWeekNormal,
115  dtWeekHighlight,
116  dtMax
117  };
118 
119  struct CellInfo
120  {
122  DayType type;
124  int x;
126  int y;
128  int textX;
130  int textY;
132  wxString text;
133  };
134 
135  CellInfo pCacheDay[Date::Calendar::maxDaysInYear];
136 
137  CellInfo pCacheWeek[Date::Calendar::maxWeeksInYear * 2];
138  uint pCacheWeekObjectID[Date::Calendar::maxWeeksInYear];
139 
141  CalendarSelect& pDialog;
142 
143  // Event table
144  DECLARE_EVENT_TABLE()
145 
146 }; // class CalendarViewStandard
147 
148 BEGIN_EVENT_TABLE(CalendarViewStandard, Panel)
150 EVT_ERASE_BACKGROUND(CalendarViewStandard::onEraseBackground)
151 END_EVENT_TABLE()
152 
153 // The font re-used for each drawing
154 enum
155 {
156  fontSize = 8,
157 
158  textDrawOffsetY = Yuni::System::windows ? -1 : 0,
159 };
160 
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"));
164 
165 CalendarViewStandard::CalendarViewStandard(wxWindow* parent, CalendarSelect& dialog):
166  Panel(parent),
167  calendar(GetCurrentStudy()->calendar),
168  pDialog(dialog)
169 {
170  SetBackgroundStyle(wxBG_STYLE_CUSTOM); // Required by both GTK and Windows
171  SetSize(recommendedWindowWidth, recommendedWindowHeight);
172  assert(parent != NULL);
173 
174  pCurrentDayYearHover = (uint)-1;
175  pDayYearRangeStart = (uint)-1;
176  pCurrentSelectionDayRange[0] = pDialog.selectionDayRange[0];
177  pCurrentSelectionDayRange[1] = pDialog.selectionDayRange[1];
178  pCacheBkgReady = false;
179 
180  for (uint i = 0; i != calendar.maxDaysInYear; ++i)
181  {
182  pCacheDay[i].x = 100000; // arbitrary - far far away
183  pCacheDay[i].type = dtNormal;
184  }
185  for (uint i = 0; i != calendar.maxWeeksInYear * 2; ++i)
186  {
187  pCacheWeek[i].x = 100000; // arbitrary - far far away
188  pCacheWeek[i].type = dtInvalid;
189  }
190 
191  wxMemoryDC dc;
192  prepareGrid(dc, calendar);
193  updateGridCells(-1, -1);
194  Dispatcher::GUI::Post(this, &CalendarViewStandard::updateSelectionText);
195  Dispatcher::GUI::Refresh(this);
196 }
197 
198 void CalendarViewStandard::selectWholeYear()
199 {
200  pDialog.pHasBeenModified = true;
201  pDialog.selectionDayRange[0] = 0;
202  pDialog.selectionDayRange[1] = 365;
203  pCurrentDayYearHover = (uint)-1;
204  pDayYearRangeStart = (uint)-1;
205 
206  updateGridCells(-1, -1);
207  updateSelectionText();
208  Refresh();
209 }
210 
211 void CalendarViewStandard::selectNone()
212 {
213  pDialog.pHasBeenModified = true;
214  pDialog.selectionDayRange[0] = (uint)-1;
215  pDialog.selectionDayRange[1] = (uint)-1;
216  pCurrentDayYearHover = (uint)-1;
217  pDayYearRangeStart = (uint)-1;
218 
219  updateGridCells(-1, -1);
220  updateSelectionText();
221  Refresh();
222 }
223 
224 void CalendarViewStandard::updateGridCells(int x, int y)
225 {
226  // note : prepareGrid must be called at least once before this routine
227  // looking for the day hover
228  for (uint d = 0; d != calendar.maxDaysInYear; ++d)
229  {
230  auto& day = pCacheDay[d];
231  if (x >= day.x && y >= day.y && x < day.x + dayWidth && y < day.y + dayWidth)
232  {
233  // Do never take into consideration the last day in leap year
234  if (d < 365)
235  {
236  pCurrentDayYearHover = d;
237  }
238  break;
239  }
240  }
241  updateSelectionDayRange();
242 
243  for (uint w = 0; w != calendar.maxWeeksInYear; ++w)
244  {
245  pCacheWeek[pCacheWeekObjectID[w]].type = dtWeekNormal;
246  }
247 
248  // updating all cells
249  for (uint d = 0; d != calendar.maxDaysInYear; ++d)
250  {
251  auto& day = pCacheDay[d];
252 
253  // hover
254  if (d == pCurrentDayYearHover)
255  {
256  for (uint i = d + 1; i < calendar.maxDaysInYear; ++i)
257  {
258  pCacheDay[i].type = (pDialog.selectionDayRange[1] != (uint)-1
259  && i < pDialog.selectionDayRange[1]
260  && i >= pDialog.selectionDayRange[0])
261  ? dtSelection
262  : dtNormal;
263  }
264 
265  // highlighting the week
266  uint week = calendar.days[d].week;
267  pCacheWeek[pCacheWeekObjectID[week]].type = dtWeekHighlight;
268  auto& range = calendar.weeks[week].daysYear;
269  if (d < pDayYearRangeStart)
270  {
271  for (uint wd = range.first; wd < range.end; ++wd)
272  {
273  pCacheDay[wd].type = dtWeek;
274  }
275  }
276  else
277  {
278  for (uint wd = d + 1; wd < range.end; ++wd)
279  {
280  pCacheDay[wd].type = dtWeek;
281  }
282  }
283 
284  // hightlighting the day where the mouse is hover
285  day.type = dtHighlight;
286  break;
287  }
288 
289  day.type = (d >= pDayYearRangeStart)
290  ? ((d == pDayYearRangeStart) ? dtHighlight : dtHighlightRange)
291  : (d >= pDialog.selectionDayRange[0] && d < pDialog.selectionDayRange[1]
292  ? dtSelection
293  : dtNormal);
294  }
295 
296  if (pDayYearRangeStart == (uint)-1)
297  {
298  // highlight (error) partial weeks for user selection
299  if (pDialog.selectionDayRange[0] != (uint)-1 && pDialog.selectionDayRange[1] != (uint)-1)
300  {
301  uint count = pDialog.selectionDayRange[1] - pDialog.selectionDayRange[0];
302  if (count < 7)
303  {
304  for (uint i = pDialog.selectionDayRange[0]; i < pDialog.selectionDayRange[1]; ++i)
305  {
306  pCacheDay[i].type = dtHighlightRangeSimulationOut;
307  }
308  }
309  else
310  {
311  uint partial = count % 7;
312  for (uint i = pDialog.selectionDayRange[1] - partial;
313  i < pDialog.selectionDayRange[1];
314  ++i)
315  {
316  pCacheDay[i].type = dtHighlightRangeSimulationOut;
317  }
318  }
319  }
320  }
321  else
322  {
323  if (pCurrentDayYearHover != (uint)-1)
324  {
325  // highlight (error) partial weeks for the current in range selection
326  uint count = pCurrentSelectionDayRange[1] - pCurrentSelectionDayRange[0] + 1;
327  if (count < 7)
328  {
329  for (uint i = pCurrentSelectionDayRange[0]; i <= pCurrentSelectionDayRange[1]; ++i)
330  {
331  pCacheDay[i].type = dtHighlightRangeSimulationOut;
332  }
333  }
334  else
335  {
336  uint partial = count % 7;
337  for (uint i = pCurrentSelectionDayRange[1] - partial + 1;
338  i <= pCurrentSelectionDayRange[1];
339  ++i)
340  {
341  pCacheDay[i].type = dtHighlightRangeSimulationOut;
342  }
343  }
344  }
345  }
346 
347  // highlight the begining of the week for the selection
348  if (pDayYearRangeStart < calendar.maxDaysInYear && pDayYearRangeStart > 0)
349  {
350  uint week = calendar.days[pDayYearRangeStart].week;
351  auto& range = calendar.weeks[week].daysYear;
352  for (uint wd = range.first; wd < pDayYearRangeStart; ++wd)
353  {
354  pCacheDay[wd].type = dtWeek;
355  }
356  }
357 }
358 
360 {
361  // Notify other components as well
363  // Update informations about the mouse position
364  pMousePosition.x = x;
365  pMousePosition.y = y;
366  if (pDayYearRangeStart == (uint)-1)
367  {
368  pCurrentDayYearHover = (uint)-1;
369  }
370 
371  updateGridCells(x, y);
372 
373  if (pDayYearRangeStart != (uint)-1)
374  {
375  updateSelectionText();
376  }
377  // refresh the component itself
378  Refresh();
379 }
380 
381 void CalendarViewStandard::onMouseDown(wxMouseEvent& evt)
382 {
383  if (pDialog.allowRangeSelection)
384  {
385  pDayYearRangeStart = pCurrentDayYearHover;
386  }
387 
388  pCurrentDayYearHover = (uint)-1;
389  const auto& position = evt.GetPosition();
390  updateGridCells(position.x, position.y);
391 
392  Dispatcher::GUI::Refresh(this);
393 }
394 
396 {
397  // keeping somewhere the current mouse selection
398  if (pDialog.allowRangeSelection)
399  {
400  pDialog.selectionDayRange[0] = pCurrentSelectionDayRange[0];
401  pDialog.selectionDayRange[1] = pCurrentSelectionDayRange[1] + 1;
402  }
403  else
404  {
405  pDialog.selectionDayRange[0] = pCurrentDayYearHover;
406  pDialog.selectionDayRange[1] = pCurrentDayYearHover + 1;
407  }
408  pDialog.pHasBeenModified = true;
409 
410  // invalidating the current mouse selection
411  if (pDialog.allowQuickSelect && pDialog.selectionDayRange[0] != (uint)-1)
412  {
413  pDialog.pCanceled = false;
414  onUpdateSelectionText.unbind();
415  Dispatcher::GUI::Close(&pDialog, 100);
416  }
417  else
418  {
419  pCurrentDayYearHover = (uint)-1;
420  pDayYearRangeStart = (uint)-1;
421 
422  updateSelectionDayRange();
423  updateGridCells(10000, 0);
424  Dispatcher::GUI::Refresh(this);
425  updateSelectionText();
426  }
427 }
428 
429 void CalendarViewStandard::onDraw(wxPaintEvent&)
430 {
431  // The DC
432  wxAutoBufferedPaintDC dc(this);
433  // Shifts the device origin so we don't have to worry
434  // about the current scroll position ourselves
435  PrepareDC(dc);
436  // Cute font
437  dc.SetFont(font);
438 
439  const wxColour bkgColor(255, 255, 255);
440 
441  if (not pCacheBkgReady)
442  {
443  pCacheBackgroundImage.Create(recommendedWindowWidth, recommendedWindowHeight);
444  wxMemoryDC memdc;
445  memdc.SelectObject(pCacheBackgroundImage);
446  prepareGrid(memdc, calendar);
447  pCacheBkgReady = true;
448  }
449 
450  dc.DrawBitmap(pCacheBackgroundImage, 0, 0, false);
451 
452  // redrawing all cells
453  struct
454  {
455  wxColour background;
456  wxColour text;
457  } colorSet[dtMax];
458 
459  colorSet[dtNormal].text.Set(60, 60, 60);
460  colorSet[dtNormal].background.Set(255, 255, 255);
461 
462  colorSet[dtWeekNormal].text.Set(170, 170, 170);
463  colorSet[dtWeekNormal].background.Set(255, 255, 255);
464 
465  colorSet[dtWeekHighlight].text.Set(0, 0, 0);
466  colorSet[dtWeekHighlight].background.Set(235, 235, 235);
467 
468  colorSet[dtHighlight].text.Set(250, 250, 250);
469  colorSet[dtHighlight].background.Set(10, 10, 10);
470 
471  colorSet[dtHighlightRange].text.Set(230, 230, 230);
472  colorSet[dtHighlightRange].background.Set(80, 80, 80);
473 
474  colorSet[dtHighlightRangeSimulationOut].text.Set(230, 230, 230);
475  colorSet[dtHighlightRangeSimulationOut].background.Set(200, 30, 30);
476 
477  colorSet[dtWeek].text.Set(50, 40, 40);
478  colorSet[dtWeek].background.Set(210, 210, 215);
479 
480  colorSet[dtSelection].text.Set(30, 30, 30);
481  colorSet[dtSelection].background.Set(157, 205, 255);
482 
483  for (uint day = 0; day != calendar.maxDaysInYear; ++day)
484  {
485  auto& cache = pCacheDay[day];
486  auto& colors = colorSet[cache.type];
487 
488  dc.SetBrush(wxBrush(colors.background, wxBRUSHSTYLE_SOLID));
489  dc.SetPen(wxPen(colors.background, 1, wxPENSTYLE_SOLID));
490  dc.SetTextForeground(colors.text);
491 
492  dc.DrawRectangle(wxRect(cache.x, cache.y, dayWidth, dayWidth));
493  dc.DrawText(cache.text, cache.textX, cache.textY);
494  }
495 
496  for (uint week = 0; week != calendar.maxWeeksInYear * 2; ++week)
497  {
498  auto& cache = pCacheWeek[week];
499  if (cache.type == dtInvalid)
500  {
501  break;
502  }
503  auto& colors = colorSet[cache.type];
504 
505  dc.SetBrush(wxBrush(colors.background, wxBRUSHSTYLE_SOLID));
506  dc.SetPen(wxPen(colors.background, 1, wxPENSTYLE_SOLID));
507  dc.SetTextForeground(colors.text);
508 
509  dc.DrawRectangle(wxRect(cache.x, cache.y, weekNumbersWidth, dayWidth));
510  dc.DrawText(cache.text, cache.textX, cache.textY);
511  }
512 }
513 
514 inline void CalendarViewStandard::updateSelectionDayRange()
515 {
516  pCurrentSelectionDayRange[0] = Math::Min(pDayYearRangeStart, pCurrentDayYearHover);
517  pCurrentSelectionDayRange[1] = Math::Max(pDayYearRangeStart, pCurrentDayYearHover);
518 }
519 
520 void CalendarViewStandard::prepareGrid(wxDC& dc, const Date::Calendar& calendar)
521 {
522  // Cute font
523  dc.SetFont(font);
524 
525  wxRect rect = GetRect();
526  const wxColour bkgColor(255, 255, 255);
527 
528  // Redraw the background
529  dc.SetPen(wxPen(bkgColor, 1, wxPENSTYLE_SOLID));
530  dc.SetBrush(wxBrush(bkgColor, wxBRUSHSTYLE_SOLID));
531  dc.DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight());
532 
533  wxRect monthRect;
534  monthRect.x = weekNumbersWidth;
535  monthRect.y = 0;
536  monthRect.width = dayWidth * 7;
537  monthRect.height = dayWidth * 6 + dayWidth /*weekdays*/ + borderWidth * 4;
538  uint dayYear = 0;
539 
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);
545 
546  wxColour weekdaysBkgColor(250, 250, 250);
547  wxColour weekdaysTextColor(40, 40, 40);
548  // wxColour monthBkgColor(230, 230, 250);
549  wxColour monthBkgColor(89, 124, 145);
550  wxColour monthTextColor(250, 250, 250);
551 
552  wxColour selectionBkgColor(175, 186, 209);
553  wxColour selectionTextColor(40, 40, 40);
554  wxColour selectionDayBkgColor(131, 139, 157);
555  wxColour selectionDayTextColor(250, 250, 250);
556 
557  uint weekIndex = 0;
558 
559  wxString text;
560  uint maxY = 0;
561 
562  for (uint month = 0; month != 12; ++month)
563  {
564  if (month > 0)
565  {
566  if (0 == (month % nbMonthPerRow))
567  {
568  monthRect.x = weekNumbersWidth;
569  monthRect.y = maxY + dayWidth + borderWidth;
570  maxY = 0;
571  }
572  else
573  {
574  monthRect.x += weekNumbersWidth + monthRect.width + spaceBetweenMonth;
575  }
576  }
577 
578  uint wx = 0;
579  uint wy = 0;
580 
581  // month name
582  dc.SetFont(fontBold);
583  {
584  uint x = decalX + monthRect.x + wx;
585  uint y = decalY + monthRect.y + wy;
586 
587  enum
588  {
589  w = dayWidth * 7,
590  };
591 
592  dc.SetPen(wxPen(monthBkgColor, 1, wxPENSTYLE_SOLID));
593  dc.SetBrush(wxBrush(monthBkgColor, wxBRUSHSTYLE_SOLID));
594  dc.DrawRectangle(wxRect(x, y, w, dayWidth));
595 
596  text = wxStringFromUTF8(calendar.text.months[month].name);
597  auto extend = dc.GetTextExtent(text);
598  dc.SetTextForeground(monthTextColor);
599  dc.DrawText(text,
600  x + w / 2 - extend.GetWidth() / 2,
601  y + dayWidth / 2 - extend.GetHeight() / 2);
602  }
603  wy += dayWidth;
604 
605  // days of the week
606  dc.SetFont(font);
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)
611  {
612  uint x = decalX + monthRect.x + wx + (wd * dayWidth);
613  uint y = decalY + monthRect.y + wy;
614 
615  dc.DrawRectangle(wxRect(x, y, dayWidth, dayWidth));
616 
617  text = Date::WeekdayToLShortString(wd);
618  auto extend = dc.GetTextExtent(text);
619  dc.DrawText(text,
620  x + dayWidth / 2 - extend.GetWidth() / 2,
621  y + dayWidth / 2 - extend.GetHeight() / 2);
622  }
623  dc.SetPen(wxPen(monthBkgColor, 1, wxPENSTYLE_SOLID));
624  wy += dayWidth;
625  {
626  uint x = decalX + monthRect.x + wx;
627  uint y = decalY + monthRect.y + wy;
628  dc.DrawLine(x, y, x + dayWidth * 7, y);
629  }
630  wy += borderWidth;
631 
632  // week numbers positions
633  uint weekNumbersX = decalX + monthRect.x + wx - weekNumbersWidth;
634  uint weekNumbersY = decalY + monthRect.y + wy;
635 
636  // Current day of the week to display
637  uint graphicalWeekday = (uint)calendar.months[month].firstWeekday;
638  wx += graphicalWeekday * dayWidth;
639  // How many days in the current month
640  uint daysPerMonth = calendar.months[month].days;
641 
642  // registering the first week number
643  {
644  auto& cacheweek = pCacheWeek[weekIndex];
645  cacheweek.x = weekNumbersX;
646  cacheweek.y = weekNumbersY;
647  cacheweek.type = dtWeekNormal;
648  }
649 
650  for (uint day = 0; day < daysPerMonth; ++day, ++dayYear)
651  {
652  uint x = decalX + monthRect.x + wx;
653  uint y = decalY + monthRect.y + wy;
654 
655  if (not graphicalWeekday)
656  {
657  if (day != 0)
658  {
659  // registering the first week number
660  ++weekIndex;
661  auto& cacheweek = pCacheWeek[weekIndex];
662  cacheweek.x = weekNumbersX;
663  cacheweek.y = weekNumbersY;
664  cacheweek.type = dtWeekNormal;
665  }
666  }
667 
668  pCacheWeek[weekIndex].textX = dayYear;
669 
670  auto& cacheday = pCacheDay[dayYear];
671  cacheday.x = x;
672  cacheday.y = y;
673 
674  cacheday.text.clear();
675  cacheday.text << (day + 1);
676 
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;
680 
681  if (y > maxY)
682  {
683  maxY = y;
684  }
685  if (++graphicalWeekday >= 7)
686  {
687  graphicalWeekday = 0;
688  wx = 0;
689  wy += dayWidth;
690  weekNumbersY += dayWidth;
691  }
692  else
693  {
694  wx += dayWidth;
695  }
696  }
697  ++weekIndex;
698  }
699 
700  // invalidating the last pseudo week
701  pCacheWeek[++weekIndex].type = dtInvalid;
702 
703  // initializing textextend for all weeks
704  for (uint week = 0; week != calendar.maxWeeksInYear; ++week)
705  {
706  pCacheWeekObjectID[week] = calendar.maxWeeksInYear * 2 - 1; // invalid and never seen
707  }
708 
709  for (uint pseudoweek = 0; pseudoweek != calendar.maxWeeksInYear * 2; ++pseudoweek)
710  {
711  auto& cache = pCacheWeek[pseudoweek];
712  if (cache.type == dtInvalid)
713  {
714  break;
715  }
716 
717  cache.text.clear();
718  if (cache.textX < calendar.maxDaysInYear)
719  {
720  uint week = calendar.days[cache.textX].week;
721  week = calendar.weeks[week].userweek;
722  // if (pCacheWeekObjectID[week] > pseudoweek)
723  // pCacheWeekObjectID[week] = pseudoweek;
724  cache.text << week;
725  }
726 
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;
730  }
731 }
732 
733 void CalendarViewStandard::updateSelectionText(YString& text, uint from, uint to)
734 {
735  auto& start = calendar.days[from];
736 
737  text << ' ';
738  if (to != (uint)-1)
739  {
740  text << "From ";
741  }
742 
743  auto realmonth = calendar.months[start.month].realmonth;
744  text << Date::WeekdayToString((int)start.weekday);
745  text << ", ";
746  text << (start.dayMonth + 1) << ' ' << Date::MonthToString((int)realmonth);
747 
748  if (to != (uint)-1)
749  {
750  auto& end = calendar.days[to];
751  realmonth = calendar.months[end.month].realmonth;
752  text << " to ";
753  text << Date::WeekdayToString((int)end.weekday);
754  text << ", ";
755  text << (end.dayMonth + 1) << ' ' << Date::MonthToString((int)realmonth);
756 
757  uint nbdays = to - from + 1;
758  if (nbdays > 1 && nbdays < 400)
759  {
760  text << " (" << nbdays;
761  if (nbdays >= 7)
762  {
763  text << " days, ";
764  uint nbweeks = nbdays / 7;
765  if (nbweeks == 1)
766  {
767  text << "1 week)";
768  }
769  else
770  {
771  text << nbweeks << " weeks)";
772  }
773  }
774  else
775  {
776  text << "days)";
777  }
778  }
779  }
780 }
781 
782 void CalendarViewStandard::updateSelectionText()
783 {
784  YString text;
785 
786  if (pDayYearRangeStart != (uint)-1)
787  {
788  text = " Selecting ";
789  uint from = pCurrentSelectionDayRange[0];
790  uint to = pCurrentSelectionDayRange[1];
791  if (to == from)
792  {
793  to = (uint)-1;
794  }
795  updateSelectionText(text, from, to);
796  }
797  else
798  {
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)
803  {
804  if (to == from)
805  {
806  to = (uint)-1;
807  }
808  updateSelectionText(text, from, to);
809  }
810  }
811 
812  if (text.empty())
813  {
814  text = "(no selection)";
815  }
816  onUpdateSelectionText(text);
817 }
818 
819 } // namespace Antares::Window
Panel implementation.
Definition: panel.h:34
static void OnMouseMoveFromExternalComponent()
Event triggered by any other component (not derived from Panel)
Definition: panel.cpp:90
Definition: date.h:180
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