xref: /haiku/src/kits/shared/CalendarView.cpp (revision 0a925409bc43bc95879729a8bf2cb611f9c9c2f2)
178092ae7SKarsten Heimrich /*
2c8b61804SAxel Dörfler  * Copyright 2007-2011, Haiku, Inc. All Rights Reserved.
378092ae7SKarsten Heimrich  * Distributed under the terms of the MIT License.
478092ae7SKarsten Heimrich  *
578092ae7SKarsten Heimrich  * Authors:
678092ae7SKarsten Heimrich  *		Julun <host.haiku@gmx.de>
778092ae7SKarsten Heimrich  */
878092ae7SKarsten Heimrich 
91b3303e7SAxel Dörfler 
1078092ae7SKarsten Heimrich #include "CalendarView.h"
1178092ae7SKarsten Heimrich 
121b3303e7SAxel Dörfler #include <stdlib.h>
1378092ae7SKarsten Heimrich 
142530274dSRyan Leavengood #include <LayoutUtils.h>
1578092ae7SKarsten Heimrich #include <Window.h>
1678092ae7SKarsten Heimrich 
1778092ae7SKarsten Heimrich 
1878092ae7SKarsten Heimrich namespace BPrivate {
1978092ae7SKarsten Heimrich 
201b3303e7SAxel Dörfler 
21c8b61804SAxel Dörfler static float
2278092ae7SKarsten Heimrich FontHeight(const BView* view)
2378092ae7SKarsten Heimrich {
2478092ae7SKarsten Heimrich 	if (!view)
2578092ae7SKarsten Heimrich 		return 0.0;
2678092ae7SKarsten Heimrich 
2778092ae7SKarsten Heimrich 	BFont font;
2878092ae7SKarsten Heimrich 	view->GetFont(&font);
2978092ae7SKarsten Heimrich 	font_height fheight;
3078092ae7SKarsten Heimrich 	font.GetHeight(&fheight);
3178092ae7SKarsten Heimrich 	return ceilf(fheight.ascent + fheight.descent + fheight.leading);
3278092ae7SKarsten Heimrich }
331b3303e7SAxel Dörfler 
34c8b61804SAxel Dörfler 
35c8b61804SAxel Dörfler // #pragma mark -
3678092ae7SKarsten Heimrich 
3778092ae7SKarsten Heimrich 
386846765fSOliver Tappe BCalendarView::BCalendarView(BRect frame, const char* name, uint32 resizeMask,
396846765fSOliver Tappe 	uint32 flags)
401b3303e7SAxel Dörfler 	:
411b3303e7SAxel Dörfler 	BView(frame, name, resizeMask, flags),
4278092ae7SKarsten Heimrich 	BInvoker(),
4378092ae7SKarsten Heimrich 	fSelectionMessage(NULL),
446846765fSOliver Tappe 	fDate(),
4578092ae7SKarsten Heimrich 	fFocusChanged(false),
4678092ae7SKarsten Heimrich 	fSelectionChanged(false),
476846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
4878092ae7SKarsten Heimrich 	fDayNameHeaderVisible(true),
4978092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible(true)
5078092ae7SKarsten Heimrich {
5178092ae7SKarsten Heimrich 	_InitObject();
5278092ae7SKarsten Heimrich }
5378092ae7SKarsten Heimrich 
5478092ae7SKarsten Heimrich 
552530274dSRyan Leavengood BCalendarView::BCalendarView(const char* name, uint32 flags)
562530274dSRyan Leavengood 	:
572530274dSRyan Leavengood 	BView(name, flags),
582530274dSRyan Leavengood 	BInvoker(),
592530274dSRyan Leavengood 	fSelectionMessage(NULL),
606846765fSOliver Tappe 	fDate(),
612530274dSRyan Leavengood 	fFocusChanged(false),
622530274dSRyan Leavengood 	fSelectionChanged(false),
636846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
641e07062bSOliver Tappe 	fDayNameHeaderVisible(true),
651e07062bSOliver Tappe 	fWeekNumberHeaderVisible(true)
661e07062bSOliver Tappe {
671e07062bSOliver Tappe 	_InitObject();
681e07062bSOliver Tappe }
691e07062bSOliver Tappe 
701e07062bSOliver Tappe 
7178092ae7SKarsten Heimrich BCalendarView::~BCalendarView()
7278092ae7SKarsten Heimrich {
7378092ae7SKarsten Heimrich 	SetSelectionMessage(NULL);
7478092ae7SKarsten Heimrich }
7578092ae7SKarsten Heimrich 
7678092ae7SKarsten Heimrich 
7778092ae7SKarsten Heimrich BCalendarView::BCalendarView(BMessage* archive)
781b3303e7SAxel Dörfler 	:
791b3303e7SAxel Dörfler 	BView(archive),
8078092ae7SKarsten Heimrich 	BInvoker(),
8178092ae7SKarsten Heimrich 	fSelectionMessage(NULL),
826846765fSOliver Tappe 	fDate(archive),
8378092ae7SKarsten Heimrich 	fFocusChanged(false),
8478092ae7SKarsten Heimrich 	fSelectionChanged(false),
856846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
8678092ae7SKarsten Heimrich 	fDayNameHeaderVisible(true),
8778092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible(true)
8878092ae7SKarsten Heimrich {
8978092ae7SKarsten Heimrich 	if (archive->HasMessage("_invokeMsg")) {
9078092ae7SKarsten Heimrich 		BMessage* invokationMessage = new BMessage;
9178092ae7SKarsten Heimrich 		archive->FindMessage("_invokeMsg", invokationMessage);
9278092ae7SKarsten Heimrich 		SetInvocationMessage(invokationMessage);
9378092ae7SKarsten Heimrich 	}
9478092ae7SKarsten Heimrich 
9578092ae7SKarsten Heimrich 	if (archive->HasMessage("_selectMsg")) {
9678092ae7SKarsten Heimrich 		BMessage* selectionMessage = new BMessage;
9778092ae7SKarsten Heimrich 		archive->FindMessage("selectMsg", selectionMessage);
9878092ae7SKarsten Heimrich 		SetSelectionMessage(selectionMessage);
9978092ae7SKarsten Heimrich 	}
10078092ae7SKarsten Heimrich 
1016846765fSOliver Tappe 	if (archive->FindInt32("_weekStart", &fStartOfWeek) != B_OK)
1026846765fSOliver Tappe 		fStartOfWeek = (int32)B_WEEKDAY_MONDAY;
10378092ae7SKarsten Heimrich 
10478092ae7SKarsten Heimrich 	if (archive->FindBool("_dayHeader", &fDayNameHeaderVisible) != B_OK)
10578092ae7SKarsten Heimrich 		fDayNameHeaderVisible = true;
10678092ae7SKarsten Heimrich 
10778092ae7SKarsten Heimrich 	if (archive->FindBool("_weekHeader", &fWeekNumberHeaderVisible) != B_OK)
10878092ae7SKarsten Heimrich 		fWeekNumberHeaderVisible = true;
10978092ae7SKarsten Heimrich 
11078092ae7SKarsten Heimrich 	_SetupDayNames();
11178092ae7SKarsten Heimrich 	_SetupDayNumbers();
11278092ae7SKarsten Heimrich 	_SetupWeekNumbers();
11378092ae7SKarsten Heimrich }
11478092ae7SKarsten Heimrich 
11578092ae7SKarsten Heimrich 
11678092ae7SKarsten Heimrich BArchivable*
11778092ae7SKarsten Heimrich BCalendarView::Instantiate(BMessage* archive)
11878092ae7SKarsten Heimrich {
11978092ae7SKarsten Heimrich 	if (validate_instantiation(archive, "BCalendarView"))
12078092ae7SKarsten Heimrich 		return new BCalendarView(archive);
12178092ae7SKarsten Heimrich 
12278092ae7SKarsten Heimrich 	return NULL;
12378092ae7SKarsten Heimrich }
12478092ae7SKarsten Heimrich 
12578092ae7SKarsten Heimrich 
12678092ae7SKarsten Heimrich status_t
12778092ae7SKarsten Heimrich BCalendarView::Archive(BMessage* archive, bool deep) const
12878092ae7SKarsten Heimrich {
12978092ae7SKarsten Heimrich 	status_t status = BView::Archive(archive, deep);
13078092ae7SKarsten Heimrich 
13178092ae7SKarsten Heimrich 	if (status == B_OK && InvocationMessage())
13278092ae7SKarsten Heimrich 		status = archive->AddMessage("_invokeMsg", InvocationMessage());
13378092ae7SKarsten Heimrich 
13478092ae7SKarsten Heimrich 	if (status == B_OK && SelectionMessage())
13578092ae7SKarsten Heimrich 		status = archive->AddMessage("_selectMsg", SelectionMessage());
13678092ae7SKarsten Heimrich 
13778092ae7SKarsten Heimrich 	if (status == B_OK)
1386846765fSOliver Tappe 		status = fDate.Archive(archive);
13978092ae7SKarsten Heimrich 
14078092ae7SKarsten Heimrich 	if (status == B_OK)
1416846765fSOliver Tappe 		status = archive->AddInt32("_weekStart", fStartOfWeek);
14278092ae7SKarsten Heimrich 
14378092ae7SKarsten Heimrich 	if (status == B_OK)
14478092ae7SKarsten Heimrich 		status = archive->AddBool("_dayHeader", fDayNameHeaderVisible);
14578092ae7SKarsten Heimrich 
14678092ae7SKarsten Heimrich 	if (status == B_OK)
14778092ae7SKarsten Heimrich 		status = archive->AddBool("_weekHeader", fWeekNumberHeaderVisible);
14878092ae7SKarsten Heimrich 
14978092ae7SKarsten Heimrich 	return status;
15078092ae7SKarsten Heimrich }
15178092ae7SKarsten Heimrich 
15278092ae7SKarsten Heimrich 
15378092ae7SKarsten Heimrich void
15478092ae7SKarsten Heimrich BCalendarView::AttachedToWindow()
15578092ae7SKarsten Heimrich {
15678092ae7SKarsten Heimrich 	BView::AttachedToWindow();
15778092ae7SKarsten Heimrich 
15878092ae7SKarsten Heimrich 	if (!Messenger().IsValid())
15978092ae7SKarsten Heimrich 		SetTarget(Window(), NULL);
16078092ae7SKarsten Heimrich }
16178092ae7SKarsten Heimrich 
16278092ae7SKarsten Heimrich 
16378092ae7SKarsten Heimrich void
16478092ae7SKarsten Heimrich BCalendarView::FrameResized(float width, float height)
16578092ae7SKarsten Heimrich {
16678092ae7SKarsten Heimrich 	Invalidate(Bounds());
16778092ae7SKarsten Heimrich }
16878092ae7SKarsten Heimrich 
16978092ae7SKarsten Heimrich 
17078092ae7SKarsten Heimrich void
17178092ae7SKarsten Heimrich BCalendarView::Draw(BRect updateRect)
17278092ae7SKarsten Heimrich {
17378092ae7SKarsten Heimrich 	if (LockLooper()) {
17478092ae7SKarsten Heimrich 		if (fFocusChanged) {
17578092ae7SKarsten Heimrich 			_DrawFocusRect();
17678092ae7SKarsten Heimrich 			UnlockLooper();
17778092ae7SKarsten Heimrich 			return;
17878092ae7SKarsten Heimrich 		}
17978092ae7SKarsten Heimrich 
18078092ae7SKarsten Heimrich 		if (fSelectionChanged) {
18178092ae7SKarsten Heimrich 			_UpdateSelection();
18278092ae7SKarsten Heimrich 			UnlockLooper();
18378092ae7SKarsten Heimrich 			return;
18478092ae7SKarsten Heimrich 		}
18578092ae7SKarsten Heimrich 
18678092ae7SKarsten Heimrich 		_DrawDays();
18778092ae7SKarsten Heimrich 		_DrawDayHeader();
18878092ae7SKarsten Heimrich 		_DrawWeekHeader();
18978092ae7SKarsten Heimrich 
19078092ae7SKarsten Heimrich 		rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
19178092ae7SKarsten Heimrich 		SetHighColor(tint_color(background, B_DARKEN_3_TINT));
19278092ae7SKarsten Heimrich 		StrokeRect(Bounds());
19378092ae7SKarsten Heimrich 
19478092ae7SKarsten Heimrich 		UnlockLooper();
19578092ae7SKarsten Heimrich 	}
19678092ae7SKarsten Heimrich }
19778092ae7SKarsten Heimrich 
19878092ae7SKarsten Heimrich 
19978092ae7SKarsten Heimrich void
20078092ae7SKarsten Heimrich BCalendarView::DrawDay(BView* owner, BRect frame, const char* text,
20178092ae7SKarsten Heimrich 	bool isSelected, bool isEnabled, bool focus)
20278092ae7SKarsten Heimrich {
20378092ae7SKarsten Heimrich 	_DrawItem(owner, frame, text, isSelected, isEnabled, focus);
20478092ae7SKarsten Heimrich }
20578092ae7SKarsten Heimrich 
20678092ae7SKarsten Heimrich 
20778092ae7SKarsten Heimrich void
20878092ae7SKarsten Heimrich BCalendarView::DrawDayName(BView* owner, BRect frame, const char* text)
20978092ae7SKarsten Heimrich {
21078092ae7SKarsten Heimrich 	// we get the full rect, fake this as the internal function
21178092ae7SKarsten Heimrich 	// shrinks the frame to work properly when drawing a day item
21278092ae7SKarsten Heimrich 	_DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true);
21378092ae7SKarsten Heimrich }
21478092ae7SKarsten Heimrich 
21578092ae7SKarsten Heimrich 
21678092ae7SKarsten Heimrich void
21778092ae7SKarsten Heimrich BCalendarView::DrawWeekNumber(BView* owner, BRect frame, const char* text)
21878092ae7SKarsten Heimrich {
21978092ae7SKarsten Heimrich 	// we get the full rect, fake this as the internal function
22078092ae7SKarsten Heimrich 	// shrinks the frame to work properly when drawing a day item
22178092ae7SKarsten Heimrich 	_DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true);
22278092ae7SKarsten Heimrich }
22378092ae7SKarsten Heimrich 
22478092ae7SKarsten Heimrich 
22578092ae7SKarsten Heimrich uint32
22678092ae7SKarsten Heimrich BCalendarView::SelectionCommand() const
22778092ae7SKarsten Heimrich {
22878092ae7SKarsten Heimrich 	if (SelectionMessage())
22978092ae7SKarsten Heimrich 		return SelectionMessage()->what;
23078092ae7SKarsten Heimrich 
23178092ae7SKarsten Heimrich 	return 0;
23278092ae7SKarsten Heimrich }
23378092ae7SKarsten Heimrich 
23478092ae7SKarsten Heimrich 
23578092ae7SKarsten Heimrich BMessage*
23678092ae7SKarsten Heimrich BCalendarView::SelectionMessage() const
23778092ae7SKarsten Heimrich {
23878092ae7SKarsten Heimrich 	return fSelectionMessage;
23978092ae7SKarsten Heimrich }
24078092ae7SKarsten Heimrich 
24178092ae7SKarsten Heimrich 
24278092ae7SKarsten Heimrich void
24378092ae7SKarsten Heimrich BCalendarView::SetSelectionMessage(BMessage* message)
24478092ae7SKarsten Heimrich {
24578092ae7SKarsten Heimrich 	delete fSelectionMessage;
24678092ae7SKarsten Heimrich 	fSelectionMessage = message;
24778092ae7SKarsten Heimrich }
24878092ae7SKarsten Heimrich 
24978092ae7SKarsten Heimrich 
25078092ae7SKarsten Heimrich uint32
25178092ae7SKarsten Heimrich BCalendarView::InvocationCommand() const
25278092ae7SKarsten Heimrich {
25378092ae7SKarsten Heimrich 	return BInvoker::Command();
25478092ae7SKarsten Heimrich }
25578092ae7SKarsten Heimrich 
25678092ae7SKarsten Heimrich 
25778092ae7SKarsten Heimrich BMessage*
25878092ae7SKarsten Heimrich BCalendarView::InvocationMessage() const
25978092ae7SKarsten Heimrich {
26078092ae7SKarsten Heimrich 	return BInvoker::Message();
26178092ae7SKarsten Heimrich }
26278092ae7SKarsten Heimrich 
26378092ae7SKarsten Heimrich 
26478092ae7SKarsten Heimrich void
26578092ae7SKarsten Heimrich BCalendarView::SetInvocationMessage(BMessage* message)
26678092ae7SKarsten Heimrich {
26778092ae7SKarsten Heimrich 	BInvoker::SetMessage(message);
26878092ae7SKarsten Heimrich }
26978092ae7SKarsten Heimrich 
27078092ae7SKarsten Heimrich 
27178092ae7SKarsten Heimrich void
27278092ae7SKarsten Heimrich BCalendarView::MakeFocus(bool state)
27378092ae7SKarsten Heimrich {
27478092ae7SKarsten Heimrich 	if (IsFocus() == state)
27578092ae7SKarsten Heimrich 		return;
27678092ae7SKarsten Heimrich 
27778092ae7SKarsten Heimrich 	BView::MakeFocus(state);
27878092ae7SKarsten Heimrich 
2791b3303e7SAxel Dörfler 	// TODO: solve this better
28078092ae7SKarsten Heimrich 	fFocusChanged = true;
28178092ae7SKarsten Heimrich 	Draw(_RectOfDay(fFocusedDay));
28278092ae7SKarsten Heimrich 	fFocusChanged = false;
28378092ae7SKarsten Heimrich }
28478092ae7SKarsten Heimrich 
28578092ae7SKarsten Heimrich 
28678092ae7SKarsten Heimrich status_t
28778092ae7SKarsten Heimrich BCalendarView::Invoke(BMessage* message)
28878092ae7SKarsten Heimrich {
28978092ae7SKarsten Heimrich 	bool notify = false;
29078092ae7SKarsten Heimrich 	uint32 kind = InvokeKind(&notify);
29178092ae7SKarsten Heimrich 
29278092ae7SKarsten Heimrich 	BMessage clone(kind);
29378092ae7SKarsten Heimrich 	status_t status = B_BAD_VALUE;
29478092ae7SKarsten Heimrich 
29578092ae7SKarsten Heimrich 	if (!message && !notify)
29678092ae7SKarsten Heimrich 		message = Message();
29778092ae7SKarsten Heimrich 
29878092ae7SKarsten Heimrich 	if (!message) {
29978092ae7SKarsten Heimrich 		if (!IsWatched())
30078092ae7SKarsten Heimrich 			return status;
30178092ae7SKarsten Heimrich 	} else
30278092ae7SKarsten Heimrich 		clone = *message;
30378092ae7SKarsten Heimrich 
30478092ae7SKarsten Heimrich 	clone.AddPointer("source", this);
30578092ae7SKarsten Heimrich 	clone.AddInt64("when", (int64)system_time());
30678092ae7SKarsten Heimrich 	clone.AddMessenger("be:sender", BMessenger(this));
30778092ae7SKarsten Heimrich 
30878092ae7SKarsten Heimrich 	int32 year;
30978092ae7SKarsten Heimrich 	int32 month;
3106846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, &month);
31178092ae7SKarsten Heimrich 
3126846765fSOliver Tappe 	clone.AddInt32("year", fDate.Year());
3136846765fSOliver Tappe 	clone.AddInt32("month", fDate.Month());
3146846765fSOliver Tappe 	clone.AddInt32("day", fDate.Day());
31578092ae7SKarsten Heimrich 
31678092ae7SKarsten Heimrich 	if (message)
31778092ae7SKarsten Heimrich 		status = BInvoker::Invoke(&clone);
31878092ae7SKarsten Heimrich 
31978092ae7SKarsten Heimrich 	SendNotices(kind, &clone);
32078092ae7SKarsten Heimrich 
32178092ae7SKarsten Heimrich 	return status;
32278092ae7SKarsten Heimrich }
32378092ae7SKarsten Heimrich 
32478092ae7SKarsten Heimrich 
32578092ae7SKarsten Heimrich void
32678092ae7SKarsten Heimrich BCalendarView::MouseDown(BPoint where)
32778092ae7SKarsten Heimrich {
32878092ae7SKarsten Heimrich 	if (!IsFocus()) {
32978092ae7SKarsten Heimrich 		MakeFocus();
33078092ae7SKarsten Heimrich 		Sync();
33178092ae7SKarsten Heimrich 		Window()->UpdateIfNeeded();
33278092ae7SKarsten Heimrich 	}
33378092ae7SKarsten Heimrich 
33478092ae7SKarsten Heimrich 	BRect frame = Bounds();
33578092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
33678092ae7SKarsten Heimrich 		frame.top += frame.Height() / 7 - 1.0;
33778092ae7SKarsten Heimrich 
33878092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible)
33978092ae7SKarsten Heimrich 		frame.left += frame.Width() / 8 - 1.0;
34078092ae7SKarsten Heimrich 
34178092ae7SKarsten Heimrich 	if (!frame.Contains(where))
34278092ae7SKarsten Heimrich 		return;
34378092ae7SKarsten Heimrich 
34478092ae7SKarsten Heimrich 	// try to set to new day
34578092ae7SKarsten Heimrich 	frame = _SetNewSelectedDay(where);
34678092ae7SKarsten Heimrich 
34778092ae7SKarsten Heimrich 	// on success
34878092ae7SKarsten Heimrich 	if (fSelectedDay != fNewSelectedDay) {
34978092ae7SKarsten Heimrich 		// update focus
35078092ae7SKarsten Heimrich 		fFocusChanged = true;
35178092ae7SKarsten Heimrich 		fNewFocusedDay = fNewSelectedDay;
35278092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
35378092ae7SKarsten Heimrich 		fFocusChanged = false;
35478092ae7SKarsten Heimrich 
35578092ae7SKarsten Heimrich 		// update selection
35678092ae7SKarsten Heimrich 		fSelectionChanged = true;
35778092ae7SKarsten Heimrich 		Draw(frame);
35878092ae7SKarsten Heimrich 		Draw(_RectOfDay(fSelectedDay));
35978092ae7SKarsten Heimrich 		fSelectionChanged = false;
36078092ae7SKarsten Heimrich 
36178092ae7SKarsten Heimrich 		// notify that selection changed
36278092ae7SKarsten Heimrich 		InvokeNotify(SelectionMessage(), B_CONTROL_MODIFIED);
36378092ae7SKarsten Heimrich 	}
36478092ae7SKarsten Heimrich 
36578092ae7SKarsten Heimrich 	int32 clicks;
36678092ae7SKarsten Heimrich 	// on double click invoke
36778092ae7SKarsten Heimrich 	BMessage* message = Looper()->CurrentMessage();
36878092ae7SKarsten Heimrich 	if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1)
36978092ae7SKarsten Heimrich 		Invoke();
37078092ae7SKarsten Heimrich }
37178092ae7SKarsten Heimrich 
37278092ae7SKarsten Heimrich 
37378092ae7SKarsten Heimrich void
37478092ae7SKarsten Heimrich BCalendarView::KeyDown(const char* bytes, int32 numBytes)
37578092ae7SKarsten Heimrich {
37678092ae7SKarsten Heimrich 	const int32 kRows = 6;
37778092ae7SKarsten Heimrich 	const int32 kColumns = 7;
37878092ae7SKarsten Heimrich 
37978092ae7SKarsten Heimrich 	int32 row = fFocusedDay.row;
38078092ae7SKarsten Heimrich 	int32 column = fFocusedDay.column;
38178092ae7SKarsten Heimrich 
38278092ae7SKarsten Heimrich 	switch (bytes[0]) {
38378092ae7SKarsten Heimrich 		case B_LEFT_ARROW:
38478092ae7SKarsten Heimrich 			column -= 1;
38578092ae7SKarsten Heimrich 			if (column < 0) {
38678092ae7SKarsten Heimrich 				column = kColumns - 1;
38778092ae7SKarsten Heimrich 				row -= 1;
38878092ae7SKarsten Heimrich 				if (row >= 0)
38978092ae7SKarsten Heimrich 					fFocusChanged = true;
39078092ae7SKarsten Heimrich 			} else
39178092ae7SKarsten Heimrich 				fFocusChanged = true;
3926846765fSOliver Tappe 			break;
39378092ae7SKarsten Heimrich 
39478092ae7SKarsten Heimrich 		case B_RIGHT_ARROW:
39578092ae7SKarsten Heimrich 			column += 1;
39678092ae7SKarsten Heimrich 			if (column == kColumns) {
39778092ae7SKarsten Heimrich 				column = 0;
39878092ae7SKarsten Heimrich 				row += 1;
39978092ae7SKarsten Heimrich 				if (row < kRows)
40078092ae7SKarsten Heimrich 					fFocusChanged = true;
40178092ae7SKarsten Heimrich 			} else
40278092ae7SKarsten Heimrich 				fFocusChanged = true;
4036846765fSOliver Tappe 			break;
40478092ae7SKarsten Heimrich 
40578092ae7SKarsten Heimrich 		case B_UP_ARROW:
40678092ae7SKarsten Heimrich 			row -= 1;
40778092ae7SKarsten Heimrich 			if (row >= 0)
40878092ae7SKarsten Heimrich 				fFocusChanged = true;
4096846765fSOliver Tappe 			break;
41078092ae7SKarsten Heimrich 
41178092ae7SKarsten Heimrich 		case B_DOWN_ARROW:
41278092ae7SKarsten Heimrich 			row += 1;
41378092ae7SKarsten Heimrich 			if (row < kRows)
41478092ae7SKarsten Heimrich 				fFocusChanged = true;
4156846765fSOliver Tappe 			break;
4166846765fSOliver Tappe 
4176846765fSOliver Tappe 		case B_PAGE_UP:
4186846765fSOliver Tappe 		{
4196846765fSOliver Tappe 			BDate date(fDate);
4206846765fSOliver Tappe 			date.AddMonths(-1);
4216846765fSOliver Tappe 			SetDate(date);
4226846765fSOliver Tappe 
4236846765fSOliver Tappe 			Invoke();
4246846765fSOliver Tappe 			break;
4256846765fSOliver Tappe 		}
4266846765fSOliver Tappe 
4276846765fSOliver Tappe 		case B_PAGE_DOWN:
4286846765fSOliver Tappe 		{
4296846765fSOliver Tappe 			BDate date(fDate);
4306846765fSOliver Tappe 			date.AddMonths(1);
4316846765fSOliver Tappe 			SetDate(date);
4326846765fSOliver Tappe 
4336846765fSOliver Tappe 			Invoke();
4346846765fSOliver Tappe 			break;
4356846765fSOliver Tappe 		}
43678092ae7SKarsten Heimrich 
43778092ae7SKarsten Heimrich 		case B_RETURN:
4386846765fSOliver Tappe 		case B_SPACE:
4396846765fSOliver Tappe 		{
44078092ae7SKarsten Heimrich 			fSelectionChanged = true;
44178092ae7SKarsten Heimrich 			BPoint pt = _RectOfDay(fFocusedDay).LeftTop();
44278092ae7SKarsten Heimrich 			Draw(_SetNewSelectedDay(pt + BPoint(4.0, 4.0)));
44378092ae7SKarsten Heimrich 			Draw(_RectOfDay(fSelectedDay));
44478092ae7SKarsten Heimrich 			fSelectionChanged = false;
44578092ae7SKarsten Heimrich 
44678092ae7SKarsten Heimrich 			Invoke();
4476846765fSOliver Tappe 			break;
4486846765fSOliver Tappe 		}
44978092ae7SKarsten Heimrich 
45078092ae7SKarsten Heimrich 		default:
45178092ae7SKarsten Heimrich 			BView::KeyDown(bytes, numBytes);
45278092ae7SKarsten Heimrich 			break;
45378092ae7SKarsten Heimrich 	}
45478092ae7SKarsten Heimrich 
45578092ae7SKarsten Heimrich 	if (fFocusChanged) {
45678092ae7SKarsten Heimrich 		fNewFocusedDay.SetTo(row, column);
45778092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
45878092ae7SKarsten Heimrich 		Draw(_RectOfDay(fNewFocusedDay));
45978092ae7SKarsten Heimrich 		fFocusChanged = false;
46078092ae7SKarsten Heimrich 	}
46178092ae7SKarsten Heimrich }
46278092ae7SKarsten Heimrich 
46378092ae7SKarsten Heimrich 
46478092ae7SKarsten Heimrich void
46578092ae7SKarsten Heimrich BCalendarView::ResizeToPreferred()
46678092ae7SKarsten Heimrich {
46778092ae7SKarsten Heimrich 	float width;
46878092ae7SKarsten Heimrich 	float height;
46978092ae7SKarsten Heimrich 
47078092ae7SKarsten Heimrich 	GetPreferredSize(&width, &height);
47178092ae7SKarsten Heimrich 	BView::ResizeTo(width, height);
47278092ae7SKarsten Heimrich }
47378092ae7SKarsten Heimrich 
47478092ae7SKarsten Heimrich 
47578092ae7SKarsten Heimrich void
47678092ae7SKarsten Heimrich BCalendarView::GetPreferredSize(float* width, float* height)
47778092ae7SKarsten Heimrich {
47878092ae7SKarsten Heimrich 	_GetPreferredSize(width, height);
47978092ae7SKarsten Heimrich }
48078092ae7SKarsten Heimrich 
48178092ae7SKarsten Heimrich 
4822530274dSRyan Leavengood BSize
4832530274dSRyan Leavengood BCalendarView::MaxSize()
4842530274dSRyan Leavengood {
4852530274dSRyan Leavengood 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
4862530274dSRyan Leavengood 		BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
4872530274dSRyan Leavengood }
4882530274dSRyan Leavengood 
4892530274dSRyan Leavengood 
4902530274dSRyan Leavengood BSize
4912530274dSRyan Leavengood BCalendarView::MinSize()
4922530274dSRyan Leavengood {
4932530274dSRyan Leavengood 	float width, height;
4942530274dSRyan Leavengood 	_GetPreferredSize(&width, &height);
4956846765fSOliver Tappe 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(width, height));
4962530274dSRyan Leavengood }
4972530274dSRyan Leavengood 
4982530274dSRyan Leavengood 
4992530274dSRyan Leavengood BSize
5002530274dSRyan Leavengood BCalendarView::PreferredSize()
5012530274dSRyan Leavengood {
5026846765fSOliver Tappe 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
5032530274dSRyan Leavengood }
5042530274dSRyan Leavengood 
5052530274dSRyan Leavengood 
50678092ae7SKarsten Heimrich int32
50778092ae7SKarsten Heimrich BCalendarView::Day() const
50878092ae7SKarsten Heimrich {
5096846765fSOliver Tappe 	return fDate.Day();
51078092ae7SKarsten Heimrich }
51178092ae7SKarsten Heimrich 
51278092ae7SKarsten Heimrich 
51378092ae7SKarsten Heimrich int32
51478092ae7SKarsten Heimrich BCalendarView::Year() const
51578092ae7SKarsten Heimrich {
51678092ae7SKarsten Heimrich 	int32 year;
5176846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, NULL);
51878092ae7SKarsten Heimrich 
51978092ae7SKarsten Heimrich 	return year;
52078092ae7SKarsten Heimrich }
52178092ae7SKarsten Heimrich 
52278092ae7SKarsten Heimrich 
52378092ae7SKarsten Heimrich int32
52478092ae7SKarsten Heimrich BCalendarView::Month() const
52578092ae7SKarsten Heimrich {
52678092ae7SKarsten Heimrich 	int32 month;
5276846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, NULL, &month);
52878092ae7SKarsten Heimrich 
52978092ae7SKarsten Heimrich 	return month;
53078092ae7SKarsten Heimrich }
53178092ae7SKarsten Heimrich 
53278092ae7SKarsten Heimrich 
533afd5ec11SAdrien Destugues bool
534afd5ec11SAdrien Destugues BCalendarView::SetDay(int32 day)
535afd5ec11SAdrien Destugues {
536afd5ec11SAdrien Destugues 	BDate date = Date();
537afd5ec11SAdrien Destugues 	date.SetDay(day);
538afd5ec11SAdrien Destugues 	if (!date.IsValid())
539afd5ec11SAdrien Destugues 		return false;
540afd5ec11SAdrien Destugues 	SetDate(date);
541afd5ec11SAdrien Destugues 	return true;
542afd5ec11SAdrien Destugues }
543afd5ec11SAdrien Destugues 
544afd5ec11SAdrien Destugues 
545afd5ec11SAdrien Destugues bool
546afd5ec11SAdrien Destugues BCalendarView::SetMonth(int32 month)
547afd5ec11SAdrien Destugues {
548afd5ec11SAdrien Destugues 	if (month < 1 || month > 12)
549afd5ec11SAdrien Destugues 		return false;
550afd5ec11SAdrien Destugues 	BDate date = Date();
551afd5ec11SAdrien Destugues 	int32 oldDay = date.Day();
552afd5ec11SAdrien Destugues 
553afd5ec11SAdrien Destugues 	date.SetMonth(month);
554afd5ec11SAdrien Destugues 	date.SetDay(1); // make sure the date is valid
555afd5ec11SAdrien Destugues 
556afd5ec11SAdrien Destugues 	// We must make sure that the day in month fits inside the new month.
557afd5ec11SAdrien Destugues 	if (oldDay > date.DaysInMonth())
558afd5ec11SAdrien Destugues 		date.SetDay(date.DaysInMonth());
559afd5ec11SAdrien Destugues 	else
560afd5ec11SAdrien Destugues 		date.SetDay(oldDay);
561afd5ec11SAdrien Destugues 	SetDate(date);
562afd5ec11SAdrien Destugues 	return true;
563afd5ec11SAdrien Destugues }
564afd5ec11SAdrien Destugues 
565afd5ec11SAdrien Destugues 
566afd5ec11SAdrien Destugues bool
567afd5ec11SAdrien Destugues BCalendarView::SetYear(int32 year)
568afd5ec11SAdrien Destugues {
569afd5ec11SAdrien Destugues 	BDate date = Date();
570afd5ec11SAdrien Destugues 
571afd5ec11SAdrien Destugues 	// This can fail when going from 29 feb. on a leap year to a non-leap year.
572afd5ec11SAdrien Destugues 	if (date.Month() == 2 && date.Day() == 29 && !date.IsLeapYear(year))
573afd5ec11SAdrien Destugues 		date.SetDay(28);
574afd5ec11SAdrien Destugues 
575afd5ec11SAdrien Destugues 	// TODO we should also handle the "hole" at the switch between Julian and
576afd5ec11SAdrien Destugues 	// Gregorian calendars, which will result in an invalid date.
577afd5ec11SAdrien Destugues 
578afd5ec11SAdrien Destugues 	date.SetYear(year);
579afd5ec11SAdrien Destugues 	SetDate(date);
580afd5ec11SAdrien Destugues 	return true;
581afd5ec11SAdrien Destugues }
582afd5ec11SAdrien Destugues 
583afd5ec11SAdrien Destugues 
58478092ae7SKarsten Heimrich BDate
58578092ae7SKarsten Heimrich BCalendarView::Date() const
58678092ae7SKarsten Heimrich {
58778092ae7SKarsten Heimrich 	int32 year;
58878092ae7SKarsten Heimrich 	int32 month;
5896846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, &month);
5906846765fSOliver Tappe 	return BDate(year, month, fDate.Day());
59178092ae7SKarsten Heimrich }
59278092ae7SKarsten Heimrich 
59378092ae7SKarsten Heimrich 
59478092ae7SKarsten Heimrich bool
59578092ae7SKarsten Heimrich BCalendarView::SetDate(const BDate& date)
59678092ae7SKarsten Heimrich {
597c1ed5d75SKarsten Heimrich 	if (!date.IsValid())
598c1ed5d75SKarsten Heimrich 		return false;
599c1ed5d75SKarsten Heimrich 
6006846765fSOliver Tappe 	if (fDate == date)
60178092ae7SKarsten Heimrich 		return true;
60278092ae7SKarsten Heimrich 
6036846765fSOliver Tappe 	if (fDate.Year() == date.Year() && fDate.Month() == date.Month()) {
6046846765fSOliver Tappe 		fDate = date;
6056846765fSOliver Tappe 
60678092ae7SKarsten Heimrich 		_SetToDay();
60778092ae7SKarsten Heimrich 		// update focus
60878092ae7SKarsten Heimrich 		fFocusChanged = true;
60978092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
61078092ae7SKarsten Heimrich 		fFocusChanged = false;
61178092ae7SKarsten Heimrich 
61278092ae7SKarsten Heimrich 		// update selection
61378092ae7SKarsten Heimrich 		fSelectionChanged = true;
61478092ae7SKarsten Heimrich 		Draw(_RectOfDay(fSelectedDay));
61578092ae7SKarsten Heimrich 		Draw(_RectOfDay(fNewSelectedDay));
61678092ae7SKarsten Heimrich 		fSelectionChanged = false;
61778092ae7SKarsten Heimrich 	} else {
6186846765fSOliver Tappe 		fDate = date;
61978092ae7SKarsten Heimrich 
62078092ae7SKarsten Heimrich 		_SetupDayNumbers();
62178092ae7SKarsten Heimrich 		_SetupWeekNumbers();
62278092ae7SKarsten Heimrich 
62378092ae7SKarsten Heimrich 		BRect frame = Bounds();
62478092ae7SKarsten Heimrich 		if (fDayNameHeaderVisible)
62578092ae7SKarsten Heimrich 			frame.top += frame.Height() / 7 - 1.0;
62678092ae7SKarsten Heimrich 
62778092ae7SKarsten Heimrich 		if (fWeekNumberHeaderVisible)
62878092ae7SKarsten Heimrich 			frame.left += frame.Width() / 8 - 1.0;
62978092ae7SKarsten Heimrich 
63078092ae7SKarsten Heimrich 		Draw(frame.InsetBySelf(4.0, 4.0));
63178092ae7SKarsten Heimrich 	}
63278092ae7SKarsten Heimrich 
63378092ae7SKarsten Heimrich 	return true;
63478092ae7SKarsten Heimrich }
63578092ae7SKarsten Heimrich 
63678092ae7SKarsten Heimrich 
6376846765fSOliver Tappe bool
6386846765fSOliver Tappe BCalendarView::SetDate(int32 year, int32 month, int32 day)
63978092ae7SKarsten Heimrich {
6406846765fSOliver Tappe 	return SetDate(BDate(year, month, day));
6416846765fSOliver Tappe }
6426846765fSOliver Tappe 
6436846765fSOliver Tappe 
6446846765fSOliver Tappe BWeekday
6456846765fSOliver Tappe BCalendarView::StartOfWeek() const
6466846765fSOliver Tappe {
6476846765fSOliver Tappe 	return BWeekday(fStartOfWeek);
64878092ae7SKarsten Heimrich }
64978092ae7SKarsten Heimrich 
65078092ae7SKarsten Heimrich 
65178092ae7SKarsten Heimrich void
6526846765fSOliver Tappe BCalendarView::SetStartOfWeek(BWeekday startOfWeek)
65378092ae7SKarsten Heimrich {
6546846765fSOliver Tappe 	if (fStartOfWeek == (int32)startOfWeek)
65578092ae7SKarsten Heimrich 		return;
65678092ae7SKarsten Heimrich 
6576846765fSOliver Tappe 	fStartOfWeek = (int32)startOfWeek;
65878092ae7SKarsten Heimrich 
65978092ae7SKarsten Heimrich 	_SetupDayNames();
66078092ae7SKarsten Heimrich 	_SetupDayNumbers();
66178092ae7SKarsten Heimrich 	_SetupWeekNumbers();
66278092ae7SKarsten Heimrich 
66378092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
66478092ae7SKarsten Heimrich }
66578092ae7SKarsten Heimrich 
66678092ae7SKarsten Heimrich 
66778092ae7SKarsten Heimrich bool
66878092ae7SKarsten Heimrich BCalendarView::IsDayNameHeaderVisible() const
66978092ae7SKarsten Heimrich {
67078092ae7SKarsten Heimrich 	return fDayNameHeaderVisible;
67178092ae7SKarsten Heimrich }
67278092ae7SKarsten Heimrich 
67378092ae7SKarsten Heimrich 
67478092ae7SKarsten Heimrich void
67578092ae7SKarsten Heimrich BCalendarView::SetDayNameHeaderVisible(bool visible)
67678092ae7SKarsten Heimrich {
67778092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible == visible)
67878092ae7SKarsten Heimrich 		return;
67978092ae7SKarsten Heimrich 
68078092ae7SKarsten Heimrich 	fDayNameHeaderVisible = visible;
68178092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
68278092ae7SKarsten Heimrich }
68378092ae7SKarsten Heimrich 
68478092ae7SKarsten Heimrich 
68578092ae7SKarsten Heimrich bool
68678092ae7SKarsten Heimrich BCalendarView::IsWeekNumberHeaderVisible() const
68778092ae7SKarsten Heimrich {
68878092ae7SKarsten Heimrich 	return fWeekNumberHeaderVisible;
68978092ae7SKarsten Heimrich }
69078092ae7SKarsten Heimrich 
69178092ae7SKarsten Heimrich 
69278092ae7SKarsten Heimrich void
69378092ae7SKarsten Heimrich BCalendarView::SetWeekNumberHeaderVisible(bool visible)
69478092ae7SKarsten Heimrich {
69578092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible == visible)
69678092ae7SKarsten Heimrich 		return;
69778092ae7SKarsten Heimrich 
69878092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible = visible;
69978092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
70078092ae7SKarsten Heimrich }
70178092ae7SKarsten Heimrich 
70278092ae7SKarsten Heimrich 
70378092ae7SKarsten Heimrich void
70478092ae7SKarsten Heimrich BCalendarView::_InitObject()
70578092ae7SKarsten Heimrich {
7066846765fSOliver Tappe 	fDate = BDate::CurrentDate(B_LOCAL_TIME);
7076846765fSOliver Tappe 
708*0a925409SAdrien Destugues 	BDateFormat().GetStartOfWeek((BWeekday*)&fStartOfWeek);
70978092ae7SKarsten Heimrich 
71078092ae7SKarsten Heimrich 	_SetupDayNames();
71178092ae7SKarsten Heimrich 	_SetupDayNumbers();
71278092ae7SKarsten Heimrich 	_SetupWeekNumbers();
71378092ae7SKarsten Heimrich }
71478092ae7SKarsten Heimrich 
71578092ae7SKarsten Heimrich 
71678092ae7SKarsten Heimrich void
71778092ae7SKarsten Heimrich BCalendarView::_SetToDay()
71878092ae7SKarsten Heimrich {
7196846765fSOliver Tappe 	BDate date(fDate.Year(), fDate.Month(), 1);
72078092ae7SKarsten Heimrich 	if (!date.IsValid())
72178092ae7SKarsten Heimrich 		return;
72278092ae7SKarsten Heimrich 
7236846765fSOliver Tappe 	const int32 firstDayOffset = (7 + date.DayOfWeek() - fStartOfWeek) % 7;
72478092ae7SKarsten Heimrich 
7256846765fSOliver Tappe 	int32 day = 1 - firstDayOffset;
72678092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
72778092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
7286846765fSOliver Tappe 			if (day == fDate.Day()) {
72978092ae7SKarsten Heimrich 				fNewFocusedDay.SetTo(row, column);
73078092ae7SKarsten Heimrich 				fNewSelectedDay.SetTo(row, column);
73178092ae7SKarsten Heimrich 				return;
73278092ae7SKarsten Heimrich 			}
7336846765fSOliver Tappe 			day++;
73478092ae7SKarsten Heimrich 		}
73578092ae7SKarsten Heimrich 	}
7366846765fSOliver Tappe 
7376846765fSOliver Tappe 	fNewFocusedDay.SetTo(0, 0);
7386846765fSOliver Tappe 	fNewSelectedDay.SetTo(0, 0);
73978092ae7SKarsten Heimrich }
74078092ae7SKarsten Heimrich 
74178092ae7SKarsten Heimrich 
74278092ae7SKarsten Heimrich void
7436846765fSOliver Tappe BCalendarView::_GetYearMonthForSelection(const Selection& selection,
7446846765fSOliver Tappe 	int32* year, int32* month) const
74578092ae7SKarsten Heimrich {
7466846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
7476846765fSOliver Tappe 	const int32 firstDayOffset
7486846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
7496846765fSOliver Tappe 	const int32 daysInMonth = startOfMonth.DaysInMonth();
75078092ae7SKarsten Heimrich 
7516846765fSOliver Tappe 	BDate date(fDate);
7526846765fSOliver Tappe 	const int32 dayOffset = selection.row * 7 + selection.column;
7536846765fSOliver Tappe 	if (dayOffset < firstDayOffset)
7546846765fSOliver Tappe 		date.AddMonths(-1);
7556846765fSOliver Tappe 	else if (dayOffset >= firstDayOffset + daysInMonth)
7566846765fSOliver Tappe 		date.AddMonths(1);
7576846765fSOliver Tappe 	if (year != NULL)
75878092ae7SKarsten Heimrich 		*year = date.Year();
7596846765fSOliver Tappe 	if (month != NULL)
76078092ae7SKarsten Heimrich 		*month = date.Month();
76178092ae7SKarsten Heimrich }
76278092ae7SKarsten Heimrich 
76378092ae7SKarsten Heimrich 
76478092ae7SKarsten Heimrich void
76578092ae7SKarsten Heimrich BCalendarView::_GetPreferredSize(float* _width, float* _height)
76678092ae7SKarsten Heimrich {
76778092ae7SKarsten Heimrich 	BFont font;
76878092ae7SKarsten Heimrich 	GetFont(&font);
76978092ae7SKarsten Heimrich 	font_height fontHeight;
77078092ae7SKarsten Heimrich 	font.GetHeight(&fontHeight);
77178092ae7SKarsten Heimrich 
77278092ae7SKarsten Heimrich 	const float height = FontHeight(this) + 4.0;
77378092ae7SKarsten Heimrich 
77478092ae7SKarsten Heimrich 	int32 rows = 7;
77578092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
77678092ae7SKarsten Heimrich 		rows = 6;
77778092ae7SKarsten Heimrich 
77878092ae7SKarsten Heimrich 	// height = font height * rows + 8 px border
77978092ae7SKarsten Heimrich 	*_height = height * rows + 8.0;
78078092ae7SKarsten Heimrich 
78178092ae7SKarsten Heimrich 	float width = 0.0;
78278092ae7SKarsten Heimrich 	for (int32 column = 0; column < 7; ++column) {
78378092ae7SKarsten Heimrich 		float tmp = StringWidth(fDayNames[column].String()) + 2.0;
78478092ae7SKarsten Heimrich 		width = tmp > width ? tmp : width;
78578092ae7SKarsten Heimrich 	}
78678092ae7SKarsten Heimrich 
78778092ae7SKarsten Heimrich 	int32 columns = 8;
78878092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
78978092ae7SKarsten Heimrich 		columns = 7;
79078092ae7SKarsten Heimrich 
79178092ae7SKarsten Heimrich 	// width = max width day name * 8 column + 8 px border
79278092ae7SKarsten Heimrich 	*_width = width * columns + 8.0;
79378092ae7SKarsten Heimrich }
79478092ae7SKarsten Heimrich 
79578092ae7SKarsten Heimrich 
79678092ae7SKarsten Heimrich void
79778092ae7SKarsten Heimrich BCalendarView::_SetupDayNames()
79878092ae7SKarsten Heimrich {
7996846765fSOliver Tappe 	for (int32 i = 0; i <= 6; ++i)
8006846765fSOliver Tappe 		fDayNames[i] = fDate.ShortDayName(1 + (fStartOfWeek - 1 + i) % 7);
80178092ae7SKarsten Heimrich }
80278092ae7SKarsten Heimrich 
80378092ae7SKarsten Heimrich 
80478092ae7SKarsten Heimrich void
80578092ae7SKarsten Heimrich BCalendarView::_SetupDayNumbers()
80678092ae7SKarsten Heimrich {
8076846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
8086846765fSOliver Tappe 	if (!startOfMonth.IsValid())
80978092ae7SKarsten Heimrich 		return;
81078092ae7SKarsten Heimrich 
81178092ae7SKarsten Heimrich 	fFocusedDay.SetTo(0, 0);
81278092ae7SKarsten Heimrich 	fSelectedDay.SetTo(0, 0);
81378092ae7SKarsten Heimrich 	fNewFocusedDay.SetTo(0, 0);
81478092ae7SKarsten Heimrich 
8156846765fSOliver Tappe 	const int32 daysInMonth = startOfMonth.DaysInMonth();
8166846765fSOliver Tappe 	const int32 firstDayOffset
8176846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
81878092ae7SKarsten Heimrich 
81978092ae7SKarsten Heimrich 	// calc the last day one month before
8206846765fSOliver Tappe 	BDate lastDayInMonthBefore(startOfMonth);
8216846765fSOliver Tappe 	lastDayInMonthBefore.AddDays(-1);
8226846765fSOliver Tappe 	const int32 lastDayBefore = lastDayInMonthBefore.DaysInMonth();
82378092ae7SKarsten Heimrich 
82478092ae7SKarsten Heimrich 	int32 counter = 0;
82578092ae7SKarsten Heimrich 	int32 firstDayAfter = 1;
82678092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
82778092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
8286846765fSOliver Tappe 			int32 day = 1 + counter - firstDayOffset;
8296846765fSOliver Tappe 			if (counter < firstDayOffset)
83078092ae7SKarsten Heimrich 				day += lastDayBefore;
8316846765fSOliver Tappe 			else if (counter >= firstDayOffset + daysInMonth)
83278092ae7SKarsten Heimrich 				day = firstDayAfter++;
8336846765fSOliver Tappe 			else if (day == fDate.Day()) {
83478092ae7SKarsten Heimrich 				fFocusedDay.SetTo(row, column);
83578092ae7SKarsten Heimrich 				fSelectedDay.SetTo(row, column);
83678092ae7SKarsten Heimrich 				fNewFocusedDay.SetTo(row, column);
83778092ae7SKarsten Heimrich 			}
83878092ae7SKarsten Heimrich 			counter++;
8396846765fSOliver Tappe 			fDayNumbers[row][column].Truncate(0);
84078092ae7SKarsten Heimrich 			fDayNumbers[row][column] << day;
84178092ae7SKarsten Heimrich 		}
84278092ae7SKarsten Heimrich 	}
84378092ae7SKarsten Heimrich }
84478092ae7SKarsten Heimrich 
8456846765fSOliver Tappe 
84678092ae7SKarsten Heimrich void
84778092ae7SKarsten Heimrich BCalendarView::_SetupWeekNumbers()
84878092ae7SKarsten Heimrich {
8496846765fSOliver Tappe 	BDate date(fDate.Year(), fDate.Month(), 1);
85078092ae7SKarsten Heimrich 	if (!date.IsValid())
85178092ae7SKarsten Heimrich 		return;
85278092ae7SKarsten Heimrich 
853c1ed5d75SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
85478092ae7SKarsten Heimrich 		fWeekNumbers[row].SetTo("");
855f0932941SMichael Pfeiffer 		fWeekNumbers[row] << date.WeekNumber();
856f0932941SMichael Pfeiffer 		date.AddDays(7);
857c1ed5d75SKarsten Heimrich 	}
85878092ae7SKarsten Heimrich }
85978092ae7SKarsten Heimrich 
86078092ae7SKarsten Heimrich 
86178092ae7SKarsten Heimrich void
86287663db4SOliver Tappe BCalendarView::_DrawDay(int32 currRow, int32 currColumn, int32 row,
86387663db4SOliver Tappe 	int32 column, int32 counter, BRect frame, const char* text, bool focus)
86478092ae7SKarsten Heimrich {
8656846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
8666846765fSOliver Tappe 	const int32 firstDayOffset
8676846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
8686846765fSOliver Tappe 	const int32 daysMonth = startOfMonth.DaysInMonth();
86978092ae7SKarsten Heimrich 
87078092ae7SKarsten Heimrich 	bool enabled = true;
87178092ae7SKarsten Heimrich 	bool selected = false;
87278092ae7SKarsten Heimrich 	// check for the current date
87378092ae7SKarsten Heimrich 	if (currRow == row  && currColumn == column) {
87478092ae7SKarsten Heimrich 		selected = true;	// draw current date selected
8756846765fSOliver Tappe 		if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth) {
87678092ae7SKarsten Heimrich 			enabled = false;	// days of month before or after
87778092ae7SKarsten Heimrich 			selected = false;	// not selected but able to get focus
87878092ae7SKarsten Heimrich 		}
87978092ae7SKarsten Heimrich 	} else {
8806846765fSOliver Tappe 		if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth)
88178092ae7SKarsten Heimrich 			enabled = false;	// days of month before or after
88278092ae7SKarsten Heimrich 	}
88378092ae7SKarsten Heimrich 
88478092ae7SKarsten Heimrich 	DrawDay(this, frame, text, selected, enabled, focus);
88578092ae7SKarsten Heimrich }
88678092ae7SKarsten Heimrich 
88778092ae7SKarsten Heimrich 
88878092ae7SKarsten Heimrich void
88978092ae7SKarsten Heimrich BCalendarView::_DrawDays()
89078092ae7SKarsten Heimrich {
89178092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
89278092ae7SKarsten Heimrich 
89378092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
89478092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
89578092ae7SKarsten Heimrich 
89678092ae7SKarsten Heimrich 	const bool isFocus = IsFocus();
89778092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
89878092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
89978092ae7SKarsten Heimrich 
90078092ae7SKarsten Heimrich 	int32 counter = 0;
90178092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
90278092ae7SKarsten Heimrich 		BRect tmp = frame;
90378092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
90478092ae7SKarsten Heimrich 			counter++;
90578092ae7SKarsten Heimrich 			const char* day = fDayNumbers[row][column].String();
90678092ae7SKarsten Heimrich 			bool focus = isFocus && focusRow == row && focusColumn == column;
90787663db4SOliver Tappe 			_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
90887663db4SOliver Tappe 				focus);
90978092ae7SKarsten Heimrich 
91078092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
91178092ae7SKarsten Heimrich 		}
91278092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
91378092ae7SKarsten Heimrich 	}
91478092ae7SKarsten Heimrich }
91578092ae7SKarsten Heimrich 
91678092ae7SKarsten Heimrich 
91778092ae7SKarsten Heimrich void
91878092ae7SKarsten Heimrich BCalendarView::_DrawFocusRect()
91978092ae7SKarsten Heimrich {
92078092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
92178092ae7SKarsten Heimrich 
92278092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
92378092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
92478092ae7SKarsten Heimrich 
92578092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
92678092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
92778092ae7SKarsten Heimrich 
92878092ae7SKarsten Heimrich 	int32 counter = 0;
92978092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
93078092ae7SKarsten Heimrich 		BRect tmp = frame;
93178092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
93278092ae7SKarsten Heimrich 			counter++;
93378092ae7SKarsten Heimrich 			if (fNewFocusedDay.row == row && fNewFocusedDay.column == column) {
93478092ae7SKarsten Heimrich 				fFocusedDay.SetTo(row, column);
93578092ae7SKarsten Heimrich 
93678092ae7SKarsten Heimrich 				bool focus = IsFocus() && true;
93778092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
93887663db4SOliver Tappe 				_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
93987663db4SOliver Tappe 					focus);
9406846765fSOliver Tappe 			} else if (focusRow == row && focusColumn == column) {
94178092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
94287663db4SOliver Tappe 				_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
94387663db4SOliver Tappe 					false);
94478092ae7SKarsten Heimrich 			}
94578092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
94678092ae7SKarsten Heimrich 		}
94778092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
94878092ae7SKarsten Heimrich 	}
94978092ae7SKarsten Heimrich }
95078092ae7SKarsten Heimrich 
95178092ae7SKarsten Heimrich 
95278092ae7SKarsten Heimrich void
95378092ae7SKarsten Heimrich BCalendarView::_DrawDayHeader()
95478092ae7SKarsten Heimrich {
95578092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
95678092ae7SKarsten Heimrich 		return;
95778092ae7SKarsten Heimrich 
95878092ae7SKarsten Heimrich 	int32 offset = 1;
95978092ae7SKarsten Heimrich 	int32 columns = 8;
96078092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible) {
96178092ae7SKarsten Heimrich 		offset = 0;
96278092ae7SKarsten Heimrich 		columns = 7;
96378092ae7SKarsten Heimrich 	}
96478092ae7SKarsten Heimrich 
96578092ae7SKarsten Heimrich 	BRect frame = Bounds();
96678092ae7SKarsten Heimrich 	frame.right = frame.Width() / columns - 1.0;
96778092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / 7.0 - 2.0;
96878092ae7SKarsten Heimrich 	frame.OffsetBy(4.0, 4.0);
96978092ae7SKarsten Heimrich 
97078092ae7SKarsten Heimrich 	for (int32 i = 0; i < columns; ++i) {
97178092ae7SKarsten Heimrich 		if (i == 0 && fWeekNumberHeaderVisible) {
97278092ae7SKarsten Heimrich 			DrawDayName(this, frame, "");
97378092ae7SKarsten Heimrich 			frame.OffsetBy(frame.Width(), 0.0);
97478092ae7SKarsten Heimrich 			continue;
97578092ae7SKarsten Heimrich 		}
97678092ae7SKarsten Heimrich 		DrawDayName(this, frame, fDayNames[i - offset].String());
97778092ae7SKarsten Heimrich 		frame.OffsetBy(frame.Width(), 0.0);
97878092ae7SKarsten Heimrich 	}
97978092ae7SKarsten Heimrich }
98078092ae7SKarsten Heimrich 
98178092ae7SKarsten Heimrich 
98278092ae7SKarsten Heimrich void
98378092ae7SKarsten Heimrich BCalendarView::_DrawWeekHeader()
98478092ae7SKarsten Heimrich {
98578092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
98678092ae7SKarsten Heimrich 		return;
98778092ae7SKarsten Heimrich 
98878092ae7SKarsten Heimrich 	int32 rows = 7;
98978092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
99078092ae7SKarsten Heimrich 		rows = 6;
99178092ae7SKarsten Heimrich 
99278092ae7SKarsten Heimrich 	BRect frame = Bounds();
99378092ae7SKarsten Heimrich 	frame.right = frame.Width() / 8.0 - 2.0;
99478092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / rows - 1.0;
99578092ae7SKarsten Heimrich 
99678092ae7SKarsten Heimrich 	float offsetY = 4.0;
99778092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
99878092ae7SKarsten Heimrich 		offsetY += frame.Height();
99978092ae7SKarsten Heimrich 
100078092ae7SKarsten Heimrich 	frame.OffsetBy(4.0, offsetY);
100178092ae7SKarsten Heimrich 
100278092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
100378092ae7SKarsten Heimrich 		DrawWeekNumber(this, frame, fWeekNumbers[row].String());
100478092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
100578092ae7SKarsten Heimrich 	}
100678092ae7SKarsten Heimrich }
100778092ae7SKarsten Heimrich 
100878092ae7SKarsten Heimrich 
100978092ae7SKarsten Heimrich void
101078092ae7SKarsten Heimrich BCalendarView::_DrawItem(BView* owner, BRect frame, const char* text,
101178092ae7SKarsten Heimrich 	bool isSelected, bool isEnabled, bool focus)
101278092ae7SKarsten Heimrich {
101378092ae7SKarsten Heimrich 	rgb_color lColor = LowColor();
101478092ae7SKarsten Heimrich 	rgb_color highColor = HighColor();
101578092ae7SKarsten Heimrich 
101678092ae7SKarsten Heimrich 	rgb_color lowColor = { 255, 255, 255, 255 };
101778092ae7SKarsten Heimrich 
101878092ae7SKarsten Heimrich 	if (isSelected) {
101978092ae7SKarsten Heimrich 		SetHighColor(tint_color(lowColor, B_DARKEN_2_TINT));
102078092ae7SKarsten Heimrich 		SetLowColor(HighColor());
102178092ae7SKarsten Heimrich 	} else
102278092ae7SKarsten Heimrich 		SetHighColor(lowColor);
102378092ae7SKarsten Heimrich 
102478092ae7SKarsten Heimrich 	FillRect(frame.InsetByCopy(1.0, 1.0));
102578092ae7SKarsten Heimrich 
102678092ae7SKarsten Heimrich 	if (focus) {
102778092ae7SKarsten Heimrich 		SetHighColor(keyboard_navigation_color());
102878092ae7SKarsten Heimrich 		StrokeRect(frame.InsetByCopy(1.0, 1.0));
102978092ae7SKarsten Heimrich 	}
103078092ae7SKarsten Heimrich 
103178092ae7SKarsten Heimrich 	rgb_color black = { 0, 0, 0, 255 };
103278092ae7SKarsten Heimrich 	SetHighColor(black);
103378092ae7SKarsten Heimrich 	if (!isEnabled)
103478092ae7SKarsten Heimrich 		SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
103578092ae7SKarsten Heimrich 
103678092ae7SKarsten Heimrich 	float offsetH = frame.Width() / 2.0;
10376846765fSOliver Tappe 	float offsetV = frame.Height() / 2.0 + FontHeight(owner) / 2.0 - 2.0;
103878092ae7SKarsten Heimrich 
10396846765fSOliver Tappe 	DrawString(text, BPoint(frame.right - offsetH - StringWidth(text) / 2.0,
10406846765fSOliver Tappe 			frame.top + offsetV));
104178092ae7SKarsten Heimrich 
104278092ae7SKarsten Heimrich 	SetLowColor(lColor);
104378092ae7SKarsten Heimrich 	SetHighColor(highColor);
104478092ae7SKarsten Heimrich }
104578092ae7SKarsten Heimrich 
104678092ae7SKarsten Heimrich 
104778092ae7SKarsten Heimrich void
104878092ae7SKarsten Heimrich BCalendarView::_UpdateSelection()
104978092ae7SKarsten Heimrich {
105078092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
105178092ae7SKarsten Heimrich 
105278092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
105378092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
105478092ae7SKarsten Heimrich 
105578092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
105678092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
105778092ae7SKarsten Heimrich 
105878092ae7SKarsten Heimrich 	int32 counter = 0;
105978092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
106078092ae7SKarsten Heimrich 		BRect tmp = frame;
106178092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
106278092ae7SKarsten Heimrich 			counter++;
106387663db4SOliver Tappe 			if (fNewSelectedDay.row == row
106487663db4SOliver Tappe 				&& fNewSelectedDay.column == column) {
106578092ae7SKarsten Heimrich 				fSelectedDay.SetTo(row, column);
106678092ae7SKarsten Heimrich 
106778092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
106887663db4SOliver Tappe 				bool focus = IsFocus() && focusRow == row
106987663db4SOliver Tappe 					&& focusColumn == column;
107078092ae7SKarsten Heimrich 				_DrawDay(row, column, row, column, counter, tmp, day, focus);
10716846765fSOliver Tappe 			} else if (currRow == row && currColumn == column) {
107278092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
107387663db4SOliver Tappe 				bool focus = IsFocus() && focusRow == row
107487663db4SOliver Tappe 					&& focusColumn == column;
107578092ae7SKarsten Heimrich 				_DrawDay(currRow, currColumn, -1, -1, counter, tmp, day, focus);
107678092ae7SKarsten Heimrich 			}
107778092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
107878092ae7SKarsten Heimrich 		}
107978092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
108078092ae7SKarsten Heimrich 	}
108178092ae7SKarsten Heimrich }
108278092ae7SKarsten Heimrich 
108378092ae7SKarsten Heimrich 
108478092ae7SKarsten Heimrich BRect
108578092ae7SKarsten Heimrich BCalendarView::_FirstCalendarItemFrame() const
108678092ae7SKarsten Heimrich {
108778092ae7SKarsten Heimrich 	int32 rows = 7;
108878092ae7SKarsten Heimrich 	int32 columns = 8;
108978092ae7SKarsten Heimrich 
109078092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
109178092ae7SKarsten Heimrich 		rows = 6;
109278092ae7SKarsten Heimrich 
109378092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
109478092ae7SKarsten Heimrich 		columns = 7;
109578092ae7SKarsten Heimrich 
109678092ae7SKarsten Heimrich 	BRect frame = Bounds();
109778092ae7SKarsten Heimrich 	frame.right = frame.Width() / columns - 1.0;
109878092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / rows - 1.0;
109978092ae7SKarsten Heimrich 
110078092ae7SKarsten Heimrich 	float offsetY = 4.0;
110178092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
110278092ae7SKarsten Heimrich 		offsetY += frame.Height();
110378092ae7SKarsten Heimrich 
110478092ae7SKarsten Heimrich 	float offsetX = 4.0;
110578092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible)
110678092ae7SKarsten Heimrich 		offsetX += frame.Width();
110778092ae7SKarsten Heimrich 
110878092ae7SKarsten Heimrich 	return frame.OffsetBySelf(offsetX, offsetY);
110978092ae7SKarsten Heimrich }
111078092ae7SKarsten Heimrich 
111178092ae7SKarsten Heimrich 
111278092ae7SKarsten Heimrich BRect
111378092ae7SKarsten Heimrich BCalendarView::_SetNewSelectedDay(const BPoint& where)
111478092ae7SKarsten Heimrich {
111578092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
111678092ae7SKarsten Heimrich 
111778092ae7SKarsten Heimrich 	int32 counter = 0;
111878092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
111978092ae7SKarsten Heimrich 		BRect tmp = frame;
112078092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
112178092ae7SKarsten Heimrich 			counter++;
112278092ae7SKarsten Heimrich 			if (tmp.Contains(where)) {
112378092ae7SKarsten Heimrich 				fNewSelectedDay.SetTo(row, column);
11246846765fSOliver Tappe 				int32 year;
11256846765fSOliver Tappe 				int32 month;
11266846765fSOliver Tappe 				_GetYearMonthForSelection(fNewSelectedDay, &year, &month);
11276846765fSOliver Tappe 				if (month == fDate.Month()) {
11286846765fSOliver Tappe 					// only change date if a day in the current month has been
11296846765fSOliver Tappe 					// selected
11306846765fSOliver Tappe 					int32 day = atoi(fDayNumbers[row][column].String());
11316846765fSOliver Tappe 					fDate.SetDate(year, month, day);
11326846765fSOliver Tappe 				}
113378092ae7SKarsten Heimrich 				return tmp;
113478092ae7SKarsten Heimrich 			}
113578092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
113678092ae7SKarsten Heimrich 		}
113778092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
113878092ae7SKarsten Heimrich 	}
113978092ae7SKarsten Heimrich 
114078092ae7SKarsten Heimrich 	return frame;
114178092ae7SKarsten Heimrich }
114278092ae7SKarsten Heimrich 
114378092ae7SKarsten Heimrich 
114478092ae7SKarsten Heimrich BRect
114578092ae7SKarsten Heimrich BCalendarView::_RectOfDay(const Selection& selection) const
114678092ae7SKarsten Heimrich {
114778092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
114878092ae7SKarsten Heimrich 
114978092ae7SKarsten Heimrich 	int32 counter = 0;
115078092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
115178092ae7SKarsten Heimrich 		BRect tmp = frame;
115278092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
115378092ae7SKarsten Heimrich 			counter++;
11546846765fSOliver Tappe 			if (selection.row == row && selection.column == column)
115578092ae7SKarsten Heimrich 				return tmp;
115678092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
115778092ae7SKarsten Heimrich 		}
115878092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
115978092ae7SKarsten Heimrich 	}
116078092ae7SKarsten Heimrich 
116178092ae7SKarsten Heimrich 	return frame;
116278092ae7SKarsten Heimrich }
116378092ae7SKarsten Heimrich 
116478092ae7SKarsten Heimrich 
116578092ae7SKarsten Heimrich }	// namespace BPrivate
1166