comctl32/monthcal: Make day drawing helpers aware of multiple calendars.
This commit is contained in:
parent
57cbb01f0c
commit
354d41685f
|
@ -531,89 +531,107 @@ static void MONTHCAL_GetMaxDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
|
|||
MONTHCAL_CalculateDayOfWeek(date, TRUE);
|
||||
}
|
||||
|
||||
/* From a given point, calculate the row (weekpos), column(daypos)
|
||||
and day in the calendar. day== 0 mean the last day of the last month
|
||||
*/
|
||||
static int MONTHCAL_CalcDayFromPos(const MONTHCAL_INFO *infoPtr, int x, int y,
|
||||
int *daypos, int *weekpos)
|
||||
/* From a given point calculate the row, column and day in the calendar,
|
||||
'day == 0' means the last day of the last month. */
|
||||
static int MONTHCAL_GetDayFromPos(const MONTHCAL_INFO *infoPtr, POINT pt, INT calIdx)
|
||||
{
|
||||
int retval, firstDay;
|
||||
RECT rcClient;
|
||||
SYSTEMTIME st = infoPtr->minSel;
|
||||
SYSTEMTIME st = infoPtr->calendars[calIdx].month;
|
||||
int firstDay, col, row;
|
||||
RECT client;
|
||||
|
||||
GetClientRect(infoPtr->hwndSelf, &rcClient);
|
||||
GetClientRect(infoPtr->hwndSelf, &client);
|
||||
|
||||
/* if the point is outside the x bounds of the window put
|
||||
it at the boundary */
|
||||
if (x > rcClient.right)
|
||||
x = rcClient.right;
|
||||
/* if the point is outside the x bounds of the window put it at the boundary */
|
||||
if (pt.x > client.right) pt.x = client.right;
|
||||
|
||||
*daypos = (x - infoPtr->calendars[0].days.left ) / infoPtr->width_increment;
|
||||
*weekpos = (y - infoPtr->calendars[0].days.top ) / infoPtr->height_increment;
|
||||
col = (pt.x - infoPtr->calendars[calIdx].days.left ) / infoPtr->width_increment;
|
||||
row = (pt.y - infoPtr->calendars[calIdx].days.top ) / infoPtr->height_increment;
|
||||
|
||||
st.wDay = 1;
|
||||
firstDay = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
|
||||
retval = *daypos + (7 * *weekpos) - firstDay;
|
||||
return retval;
|
||||
return col + 7 * row - firstDay;
|
||||
}
|
||||
|
||||
/* Sets the RECT struct r to the rectangle around the date
|
||||
/* Get day position for given date and calendar
|
||||
*
|
||||
* PARAMETERS
|
||||
*
|
||||
* [I] infoPtr : pointer to control data
|
||||
* [I] date : date value
|
||||
* [O] x : day column (zero based)
|
||||
* [O] y : week column (zero based)
|
||||
* [O] col : day column (zero based)
|
||||
* [O] row : week column (zero based)
|
||||
* [I] calIdx : calendar index
|
||||
*/
|
||||
static void MONTHCAL_CalcDayXY(const MONTHCAL_INFO *infoPtr,
|
||||
const SYSTEMTIME *date, INT *x, INT *y)
|
||||
static void MONTHCAL_GetDayPos(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date,
|
||||
INT *col, INT *row, INT calIdx)
|
||||
{
|
||||
SYSTEMTIME st = infoPtr->minSel;
|
||||
LONG cmp;
|
||||
int first;
|
||||
SYSTEMTIME st = infoPtr->calendars[calIdx].month;
|
||||
INT first;
|
||||
|
||||
st.wDay = 1;
|
||||
first = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
|
||||
|
||||
cmp = MONTHCAL_CompareMonths(date, &infoPtr->minSel);
|
||||
if (calIdx == 0 || calIdx == infoPtr->cal_num-1) {
|
||||
const SYSTEMTIME *cal = &infoPtr->calendars[calIdx].month;
|
||||
LONG cmp = MONTHCAL_CompareMonths(date, &st);
|
||||
|
||||
/* previous month */
|
||||
if (cmp == -1) {
|
||||
*x = (first - MONTHCAL_MonthLength(date->wMonth, infoPtr->minSel.wYear) + date->wDay) % 7;
|
||||
*y = 0;
|
||||
*col = (first - MONTHCAL_MonthLength(date->wMonth, cal->wYear) + date->wDay) % 7;
|
||||
*row = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* next month calculation is same as for current,
|
||||
just add current month length */
|
||||
if(cmp == 1) {
|
||||
first += MONTHCAL_MonthLength(infoPtr->minSel.wMonth, infoPtr->minSel.wYear);
|
||||
/* next month calculation is same as for current, just add current month length */
|
||||
if (cmp == 1)
|
||||
first += MONTHCAL_MonthLength(cal->wMonth, cal->wYear);
|
||||
}
|
||||
|
||||
*x = (date->wDay + first) % 7;
|
||||
*y = (date->wDay + first - *x) / 7;
|
||||
*col = (date->wDay + first) % 7;
|
||||
*row = (date->wDay + first - *col) / 7;
|
||||
}
|
||||
|
||||
|
||||
/* x: column(day), y: row(week) */
|
||||
static inline void MONTHCAL_CalcDayRect(const MONTHCAL_INFO *infoPtr, RECT *r, int x, int y)
|
||||
/* returns bounding box for day in given position in given calendar */
|
||||
static inline void MONTHCAL_GetDayRectI(const MONTHCAL_INFO *infoPtr, RECT *r,
|
||||
INT col, INT row, INT calIdx)
|
||||
{
|
||||
r->left = infoPtr->calendars[0].days.left + x * infoPtr->width_increment;
|
||||
r->left = infoPtr->calendars[calIdx].days.left + col * infoPtr->width_increment;
|
||||
r->right = r->left + infoPtr->width_increment;
|
||||
r->top = infoPtr->calendars[0].days.top + y * infoPtr->height_increment;
|
||||
r->top = infoPtr->calendars[calIdx].days.top + row * infoPtr->height_increment;
|
||||
r->bottom = r->top + infoPtr->textHeight;
|
||||
}
|
||||
|
||||
|
||||
/* Sets the RECT struct r to the rectangle around the date */
|
||||
static inline void MONTHCAL_CalcPosFromDay(const MONTHCAL_INFO *infoPtr,
|
||||
const SYSTEMTIME *date, RECT *r)
|
||||
/* Returns bounding box for given date
|
||||
*
|
||||
* NOTE: when calendar index is unknown pass -1
|
||||
*/
|
||||
static inline void MONTHCAL_GetDayRect(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date,
|
||||
RECT *r, INT calIdx)
|
||||
{
|
||||
int x, y;
|
||||
INT col, row;
|
||||
|
||||
MONTHCAL_CalcDayXY(infoPtr, date, &x, &y);
|
||||
MONTHCAL_CalcDayRect(infoPtr, r, x, y);
|
||||
if (calIdx == -1)
|
||||
{
|
||||
INT cmp = MONTHCAL_CompareMonths(date, &infoPtr->calendars[0].month);
|
||||
|
||||
if (cmp <= 0)
|
||||
calIdx = 0;
|
||||
else
|
||||
{
|
||||
cmp = MONTHCAL_CompareMonths(date, &infoPtr->calendars[infoPtr->cal_num-1].month);
|
||||
if (cmp >= 0)
|
||||
calIdx = infoPtr->cal_num-1;
|
||||
else
|
||||
{
|
||||
for (calIdx = 1; calIdx < infoPtr->cal_num-1; calIdx++)
|
||||
if (MONTHCAL_CompareMonths(date, &infoPtr->calendars[calIdx].month) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MONTHCAL_GetDayPos(infoPtr, date, &col, &row, calIdx);
|
||||
MONTHCAL_GetDayRectI(infoPtr, r, col, row, calIdx);
|
||||
}
|
||||
|
||||
/* Focused day helper:
|
||||
|
@ -635,13 +653,13 @@ static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st)
|
|||
if(MONTHCAL_IsDateEqual(&infoPtr->focusedSel, st)) return FALSE;
|
||||
|
||||
/* invalidate old focused day */
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r);
|
||||
MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
|
||||
InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
|
||||
|
||||
infoPtr->focusedSel = *st;
|
||||
}
|
||||
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r);
|
||||
MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
|
||||
|
||||
if(!st && MONTHCAL_ValidateDate(&infoPtr->focusedSel))
|
||||
infoPtr->focusedSel = st_null;
|
||||
|
@ -674,9 +692,10 @@ static void MONTHCAL_Circle(const MONTHCAL_INFO *infoPtr, HDC hdc, const RECT *r
|
|||
static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc,
|
||||
const SYSTEMTIME *date)
|
||||
{
|
||||
RECT day_rect;
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, date, &day_rect);
|
||||
MONTHCAL_Circle(infoPtr, hdc, &day_rect);
|
||||
RECT r;
|
||||
|
||||
MONTHCAL_GetDayRect(infoPtr, date, &r, -1);
|
||||
MONTHCAL_Circle(infoPtr, hdc, &r);
|
||||
}
|
||||
|
||||
static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st,
|
||||
|
@ -691,13 +710,12 @@ static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEM
|
|||
|
||||
/* no need to check styles: when selection is not valid, it is set to zero.
|
||||
1 < day < 31, so everything is OK */
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, st, &r);
|
||||
MONTHCAL_GetDayRect(infoPtr, st, &r, -1);
|
||||
if(!IntersectRect(&r_temp, &(ps->rcPaint), &r)) return;
|
||||
|
||||
if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) &&
|
||||
(MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0))
|
||||
{
|
||||
|
||||
TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
|
||||
TRACE("%s\n", wine_dbgstr_rect(&r));
|
||||
oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
|
||||
|
@ -723,7 +741,6 @@ static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEM
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direction button)
|
||||
{
|
||||
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
|
||||
|
@ -760,6 +777,7 @@ static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direc
|
|||
DrawFrameControl(hdc, r, DFC_SCROLL, style);
|
||||
}
|
||||
}
|
||||
|
||||
/* paint a title with buttons and month/year string */
|
||||
static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
|
||||
{
|
||||
|
@ -924,7 +942,9 @@ static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, cons
|
|||
|
||||
col = infoPtr->dwStyle & MCS_NOTODAYCIRCLE ? 0 : 1;
|
||||
if (infoPtr->dwStyle & MCS_WEEKNUMBERS) col--;
|
||||
MONTHCAL_CalcDayRect(infoPtr, &text_rect, col, 6);
|
||||
/* TODO: when multiple calendars layout is calculated use first column/last row calendar for that
|
||||
imaginary day position */
|
||||
MONTHCAL_GetDayRectI(infoPtr, &text_rect, col, 6, 0);
|
||||
box_rect = text_rect;
|
||||
|
||||
GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL,
|
||||
|
@ -957,7 +977,7 @@ static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc,
|
|||
if(!MONTHCAL_IsDateEqual(&infoPtr->focusedSel, &st_null))
|
||||
{
|
||||
RECT r;
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r);
|
||||
MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
|
||||
DrawFocusRect(hdc, &r);
|
||||
}
|
||||
}
|
||||
|
@ -1450,8 +1470,8 @@ MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
|
|||
RECT r_prev, r_new;
|
||||
|
||||
prev.wDay = day;
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, &prev, &r_prev);
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, curSel, &r_new);
|
||||
MONTHCAL_GetDayRect(infoPtr, &prev, &r_prev, -1);
|
||||
MONTHCAL_GetDayRect(infoPtr, curSel, &r_new, -1);
|
||||
|
||||
InvalidateRect(infoPtr->hwndSelf, &r_prev, FALSE);
|
||||
InvalidateRect(infoPtr->hwndSelf, &r_new, FALSE);
|
||||
|
@ -1583,8 +1603,8 @@ MONTHCAL_UpdateToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
|
|||
|
||||
if(MONTHCAL_IsDateEqual(today, &infoPtr->todaysDate)) return FALSE;
|
||||
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->todaysDate, &old_r);
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, today, &new_r);
|
||||
MONTHCAL_GetDayRect(infoPtr, &infoPtr->todaysDate, &old_r, -1);
|
||||
MONTHCAL_GetDayRect(infoPtr, today, &new_r, -1);
|
||||
|
||||
infoPtr->todaysDate = *today;
|
||||
|
||||
|
@ -1642,9 +1662,9 @@ static inline UINT fill_hittest_info(const MCHITTESTINFO *src, MCHITTESTINFO *de
|
|||
static LRESULT
|
||||
MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
|
||||
{
|
||||
INT day, wday, wnum, calIdx;
|
||||
MCHITTESTINFO htinfo;
|
||||
SYSTEMTIME ht_month;
|
||||
INT day, calIdx;
|
||||
UINT x, y;
|
||||
|
||||
if(!lpht || lpht->cbSize < MCHITTESTINFO_V1_SIZE) return -1;
|
||||
|
@ -1725,7 +1745,7 @@ MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
|
|||
}
|
||||
|
||||
/* days area (including week days and week numbers */
|
||||
day = MONTHCAL_CalcDayFromPos(infoPtr, x, y, &wday, &wnum);
|
||||
day = MONTHCAL_GetDayFromPos(infoPtr, lpht->pt, calIdx);
|
||||
if (PtInRect(&infoPtr->calendars[calIdx].wdays, lpht->pt))
|
||||
{
|
||||
htinfo.uHit = MCHT_CALENDARDAY;
|
||||
|
@ -1735,7 +1755,7 @@ MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
|
|||
htinfo.st.wDay = (day < 1) ?
|
||||
MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day : day;
|
||||
|
||||
MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow);
|
||||
MONTHCAL_GetDayPos(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow, calIdx);
|
||||
}
|
||||
else if(PtInRect(&infoPtr->calendars[calIdx].weeknums, lpht->pt))
|
||||
{
|
||||
|
@ -1782,8 +1802,8 @@ MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
|
|||
htinfo.st.wDay = day;
|
||||
}
|
||||
|
||||
MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow);
|
||||
MONTHCAL_CalcDayRect(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow);
|
||||
MONTHCAL_GetDayPos(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow, calIdx);
|
||||
MONTHCAL_GetDayRectI(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow, calIdx);
|
||||
/* always update day of week */
|
||||
MONTHCAL_CalculateDayOfWeek(&htinfo.st, TRUE);
|
||||
}
|
||||
|
@ -2206,6 +2226,7 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
|
|||
ht.cbSize = sizeof(MCHITTESTINFO);
|
||||
ht.pt.x = (short)LOWORD(lParam);
|
||||
ht.pt.y = (short)HIWORD(lParam);
|
||||
ht.iOffset = -1;
|
||||
|
||||
hit = MONTHCAL_HitTest(infoPtr, &ht);
|
||||
|
||||
|
@ -2222,7 +2243,7 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
|
|||
/* if pointer is over focused day still there's nothing to do */
|
||||
if(!MONTHCAL_SetDayFocus(infoPtr, &ht.st)) return 0;
|
||||
|
||||
MONTHCAL_CalcPosFromDay(infoPtr, &ht.st, &r);
|
||||
MONTHCAL_GetDayRect(infoPtr, &ht.st, &r, ht.iOffset);
|
||||
|
||||
if(infoPtr->dwStyle & MCS_MULTISELECT) {
|
||||
SYSTEMTIME st[2];
|
||||
|
|
Loading…
Reference in New Issue