comctl32/monthcal: Make day drawing helpers aware of multiple calendars.

This commit is contained in:
Nikolay Sivov 2011-09-04 19:48:28 +04:00 committed by Alexandre Julliard
parent 57cbb01f0c
commit 354d41685f
1 changed files with 93 additions and 72 deletions

View File

@ -531,89 +531,107 @@ static void MONTHCAL_GetMaxDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
MONTHCAL_CalculateDayOfWeek(date, TRUE); MONTHCAL_CalculateDayOfWeek(date, TRUE);
} }
/* From a given point, calculate the row (weekpos), column(daypos) /* From a given point calculate the row, column and day in the calendar,
and day in the calendar. day== 0 mean the last day of the last month 'day == 0' means the last day of the last month. */
*/ static int MONTHCAL_GetDayFromPos(const MONTHCAL_INFO *infoPtr, POINT pt, INT calIdx)
static int MONTHCAL_CalcDayFromPos(const MONTHCAL_INFO *infoPtr, int x, int y,
int *daypos, int *weekpos)
{ {
int retval, firstDay; SYSTEMTIME st = infoPtr->calendars[calIdx].month;
RECT rcClient; int firstDay, col, row;
SYSTEMTIME st = infoPtr->minSel; RECT client;
GetClientRect(infoPtr->hwndSelf, &rcClient); GetClientRect(infoPtr->hwndSelf, &client);
/* if the point is outside the x bounds of the window put /* if the point is outside the x bounds of the window put it at the boundary */
it at the boundary */ if (pt.x > client.right) pt.x = client.right;
if (x > rcClient.right)
x = rcClient.right;
*daypos = (x - infoPtr->calendars[0].days.left ) / infoPtr->width_increment; col = (pt.x - infoPtr->calendars[calIdx].days.left ) / infoPtr->width_increment;
*weekpos = (y - infoPtr->calendars[0].days.top ) / infoPtr->height_increment; row = (pt.y - infoPtr->calendars[calIdx].days.top ) / infoPtr->height_increment;
st.wDay = 1; st.wDay = 1;
firstDay = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7; firstDay = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
retval = *daypos + (7 * *weekpos) - firstDay; return col + 7 * row - firstDay;
return retval;
} }
/* Sets the RECT struct r to the rectangle around the date /* Get day position for given date and calendar
* *
* PARAMETERS * PARAMETERS
* *
* [I] infoPtr : pointer to control data * [I] infoPtr : pointer to control data
* [I] date : date value * [I] date : date value
* [O] x : day column (zero based) * [O] col : day column (zero based)
* [O] y : week column (zero based) * [O] row : week column (zero based)
* [I] calIdx : calendar index
*/ */
static void MONTHCAL_CalcDayXY(const MONTHCAL_INFO *infoPtr, static void MONTHCAL_GetDayPos(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date,
const SYSTEMTIME *date, INT *x, INT *y) INT *col, INT *row, INT calIdx)
{ {
SYSTEMTIME st = infoPtr->minSel; SYSTEMTIME st = infoPtr->calendars[calIdx].month;
LONG cmp; INT first;
int first;
st.wDay = 1; st.wDay = 1;
first = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7; 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 */ /* previous month */
if(cmp == -1) { if (cmp == -1) {
*x = (first - MONTHCAL_MonthLength(date->wMonth, infoPtr->minSel.wYear) + date->wDay) % 7; *col = (first - MONTHCAL_MonthLength(date->wMonth, cal->wYear) + date->wDay) % 7;
*y = 0; *row = 0;
return; return;
}
/* next month calculation is same as for current, just add current month length */
if (cmp == 1)
first += MONTHCAL_MonthLength(cal->wMonth, cal->wYear);
} }
/* next month calculation is same as for current, *col = (date->wDay + first) % 7;
just add current month length */ *row = (date->wDay + first - *col) / 7;
if(cmp == 1) {
first += MONTHCAL_MonthLength(infoPtr->minSel.wMonth, infoPtr->minSel.wYear);
}
*x = (date->wDay + first) % 7;
*y = (date->wDay + first - *x) / 7;
} }
/* returns bounding box for day in given position in given calendar */
/* x: column(day), y: row(week) */ static inline void MONTHCAL_GetDayRectI(const MONTHCAL_INFO *infoPtr, RECT *r,
static inline void MONTHCAL_CalcDayRect(const MONTHCAL_INFO *infoPtr, RECT *r, int x, int y) 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->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; r->bottom = r->top + infoPtr->textHeight;
} }
/* Returns bounding box for given date
/* Sets the RECT struct r to the rectangle around the date */ *
static inline void MONTHCAL_CalcPosFromDay(const MONTHCAL_INFO *infoPtr, * NOTE: when calendar index is unknown pass -1
const SYSTEMTIME *date, RECT *r) */
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); if (calIdx == -1)
MONTHCAL_CalcDayRect(infoPtr, r, x, y); {
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: /* 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; if(MONTHCAL_IsDateEqual(&infoPtr->focusedSel, st)) return FALSE;
/* invalidate old focused day */ /* invalidate old focused day */
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r); MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
InvalidateRect(infoPtr->hwndSelf, &r, FALSE); InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
infoPtr->focusedSel = *st; infoPtr->focusedSel = *st;
} }
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r); MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
if(!st && MONTHCAL_ValidateDate(&infoPtr->focusedSel)) if(!st && MONTHCAL_ValidateDate(&infoPtr->focusedSel))
infoPtr->focusedSel = st_null; 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, static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc,
const SYSTEMTIME *date) const SYSTEMTIME *date)
{ {
RECT day_rect; RECT r;
MONTHCAL_CalcPosFromDay(infoPtr, date, &day_rect);
MONTHCAL_Circle(infoPtr, hdc, &day_rect); MONTHCAL_GetDayRect(infoPtr, date, &r, -1);
MONTHCAL_Circle(infoPtr, hdc, &r);
} }
static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st, 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. /* no need to check styles: when selection is not valid, it is set to zero.
1 < day < 31, so everything is OK */ 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(!IntersectRect(&r_temp, &(ps->rcPaint), &r)) return;
if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) && if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) &&
(MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0)) (MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0))
{ {
TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay); TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
TRACE("%s\n", wine_dbgstr_rect(&r)); TRACE("%s\n", wine_dbgstr_rect(&r));
oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]); 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) static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direction button)
{ {
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf); 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); DrawFrameControl(hdc, r, DFC_SCROLL, style);
} }
} }
/* paint a title with buttons and month/year string */ /* paint a title with buttons and month/year string */
static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx) 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; col = infoPtr->dwStyle & MCS_NOTODAYCIRCLE ? 0 : 1;
if (infoPtr->dwStyle & MCS_WEEKNUMBERS) col--; 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; box_rect = text_rect;
GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL, 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)) if(!MONTHCAL_IsDateEqual(&infoPtr->focusedSel, &st_null))
{ {
RECT r; RECT r;
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r); MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
DrawFocusRect(hdc, &r); DrawFocusRect(hdc, &r);
} }
} }
@ -1450,8 +1470,8 @@ MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
RECT r_prev, r_new; RECT r_prev, r_new;
prev.wDay = day; prev.wDay = day;
MONTHCAL_CalcPosFromDay(infoPtr, &prev, &r_prev); MONTHCAL_GetDayRect(infoPtr, &prev, &r_prev, -1);
MONTHCAL_CalcPosFromDay(infoPtr, curSel, &r_new); MONTHCAL_GetDayRect(infoPtr, curSel, &r_new, -1);
InvalidateRect(infoPtr->hwndSelf, &r_prev, FALSE); InvalidateRect(infoPtr->hwndSelf, &r_prev, FALSE);
InvalidateRect(infoPtr->hwndSelf, &r_new, 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; if(MONTHCAL_IsDateEqual(today, &infoPtr->todaysDate)) return FALSE;
MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->todaysDate, &old_r); MONTHCAL_GetDayRect(infoPtr, &infoPtr->todaysDate, &old_r, -1);
MONTHCAL_CalcPosFromDay(infoPtr, today, &new_r); MONTHCAL_GetDayRect(infoPtr, today, &new_r, -1);
infoPtr->todaysDate = *today; infoPtr->todaysDate = *today;
@ -1642,9 +1662,9 @@ static inline UINT fill_hittest_info(const MCHITTESTINFO *src, MCHITTESTINFO *de
static LRESULT static LRESULT
MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht) MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
{ {
INT day, wday, wnum, calIdx;
MCHITTESTINFO htinfo; MCHITTESTINFO htinfo;
SYSTEMTIME ht_month; SYSTEMTIME ht_month;
INT day, calIdx;
UINT x, y; UINT x, y;
if(!lpht || lpht->cbSize < MCHITTESTINFO_V1_SIZE) return -1; 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 */ /* 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)) if (PtInRect(&infoPtr->calendars[calIdx].wdays, lpht->pt))
{ {
htinfo.uHit = MCHT_CALENDARDAY; htinfo.uHit = MCHT_CALENDARDAY;
@ -1735,7 +1755,7 @@ MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
htinfo.st.wDay = (day < 1) ? htinfo.st.wDay = (day < 1) ?
MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day : day; 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)) 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; htinfo.st.wDay = day;
} }
MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow); MONTHCAL_GetDayPos(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow, calIdx);
MONTHCAL_CalcDayRect(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow); MONTHCAL_GetDayRectI(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow, calIdx);
/* always update day of week */ /* always update day of week */
MONTHCAL_CalculateDayOfWeek(&htinfo.st, TRUE); MONTHCAL_CalculateDayOfWeek(&htinfo.st, TRUE);
} }
@ -2206,6 +2226,7 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
ht.cbSize = sizeof(MCHITTESTINFO); ht.cbSize = sizeof(MCHITTESTINFO);
ht.pt.x = (short)LOWORD(lParam); ht.pt.x = (short)LOWORD(lParam);
ht.pt.y = (short)HIWORD(lParam); ht.pt.y = (short)HIWORD(lParam);
ht.iOffset = -1;
hit = MONTHCAL_HitTest(infoPtr, &ht); 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 pointer is over focused day still there's nothing to do */
if(!MONTHCAL_SetDayFocus(infoPtr, &ht.st)) return 0; 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) { if(infoPtr->dwStyle & MCS_MULTISELECT) {
SYSTEMTIME st[2]; SYSTEMTIME st[2];