xref: /haiku/src/kits/shared/CalendarView.cpp (revision 9d30b95ab363c3c9d8347a23246a72a454c6eb82)
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 
1422d88eb4SAkshay Agarwal #include <DateFormat.h>
152530274dSRyan Leavengood #include <LayoutUtils.h>
1678092ae7SKarsten Heimrich #include <Window.h>
1778092ae7SKarsten Heimrich 
1878092ae7SKarsten Heimrich 
1978092ae7SKarsten Heimrich namespace BPrivate {
2078092ae7SKarsten Heimrich 
211b3303e7SAxel Dörfler 
22c8b61804SAxel Dörfler static float
2378092ae7SKarsten Heimrich FontHeight(const BView* view)
2478092ae7SKarsten Heimrich {
2578092ae7SKarsten Heimrich 	if (!view)
2678092ae7SKarsten Heimrich 		return 0.0;
2778092ae7SKarsten Heimrich 
2878092ae7SKarsten Heimrich 	BFont font;
2978092ae7SKarsten Heimrich 	view->GetFont(&font);
3078092ae7SKarsten Heimrich 	font_height fheight;
3178092ae7SKarsten Heimrich 	font.GetHeight(&fheight);
3278092ae7SKarsten Heimrich 	return ceilf(fheight.ascent + fheight.descent + fheight.leading);
3378092ae7SKarsten Heimrich }
341b3303e7SAxel Dörfler 
35c8b61804SAxel Dörfler 
36c8b61804SAxel Dörfler // #pragma mark -
3778092ae7SKarsten Heimrich 
3878092ae7SKarsten Heimrich 
396846765fSOliver Tappe BCalendarView::BCalendarView(BRect frame, const char* name, uint32 resizeMask,
406846765fSOliver Tappe 	uint32 flags)
411b3303e7SAxel Dörfler 	:
421b3303e7SAxel Dörfler 	BView(frame, name, resizeMask, flags),
4378092ae7SKarsten Heimrich 	BInvoker(),
4478092ae7SKarsten Heimrich 	fSelectionMessage(NULL),
456846765fSOliver Tappe 	fDate(),
468013f2e0SAkshay Agarwal 	fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME)),
4778092ae7SKarsten Heimrich 	fFocusChanged(false),
4878092ae7SKarsten Heimrich 	fSelectionChanged(false),
498013f2e0SAkshay Agarwal 	fCurrentDayChanged(false),
506846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
5178092ae7SKarsten Heimrich 	fDayNameHeaderVisible(true),
5278092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible(true)
5378092ae7SKarsten Heimrich {
5478092ae7SKarsten Heimrich 	_InitObject();
5578092ae7SKarsten Heimrich }
5678092ae7SKarsten Heimrich 
5778092ae7SKarsten Heimrich 
582530274dSRyan Leavengood BCalendarView::BCalendarView(const char* name, uint32 flags)
592530274dSRyan Leavengood 	:
602530274dSRyan Leavengood 	BView(name, flags),
612530274dSRyan Leavengood 	BInvoker(),
622530274dSRyan Leavengood 	fSelectionMessage(NULL),
636846765fSOliver Tappe 	fDate(),
648013f2e0SAkshay Agarwal 	fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME)),
652530274dSRyan Leavengood 	fFocusChanged(false),
662530274dSRyan Leavengood 	fSelectionChanged(false),
678013f2e0SAkshay Agarwal 	fCurrentDayChanged(false),
686846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
691e07062bSOliver Tappe 	fDayNameHeaderVisible(true),
701e07062bSOliver Tappe 	fWeekNumberHeaderVisible(true)
711e07062bSOliver Tappe {
721e07062bSOliver Tappe 	_InitObject();
731e07062bSOliver Tappe }
741e07062bSOliver Tappe 
751e07062bSOliver Tappe 
7678092ae7SKarsten Heimrich BCalendarView::~BCalendarView()
7778092ae7SKarsten Heimrich {
7878092ae7SKarsten Heimrich 	SetSelectionMessage(NULL);
7978092ae7SKarsten Heimrich }
8078092ae7SKarsten Heimrich 
8178092ae7SKarsten Heimrich 
8278092ae7SKarsten Heimrich BCalendarView::BCalendarView(BMessage* archive)
831b3303e7SAxel Dörfler 	:
841b3303e7SAxel Dörfler 	BView(archive),
8578092ae7SKarsten Heimrich 	BInvoker(),
8678092ae7SKarsten Heimrich 	fSelectionMessage(NULL),
876846765fSOliver Tappe 	fDate(archive),
888013f2e0SAkshay Agarwal 	fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME)),
8978092ae7SKarsten Heimrich 	fFocusChanged(false),
9078092ae7SKarsten Heimrich 	fSelectionChanged(false),
918013f2e0SAkshay Agarwal 	fCurrentDayChanged(false),
926846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
9378092ae7SKarsten Heimrich 	fDayNameHeaderVisible(true),
9478092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible(true)
9578092ae7SKarsten Heimrich {
9678092ae7SKarsten Heimrich 	if (archive->HasMessage("_invokeMsg")) {
9778092ae7SKarsten Heimrich 		BMessage* invokationMessage = new BMessage;
9878092ae7SKarsten Heimrich 		archive->FindMessage("_invokeMsg", invokationMessage);
9978092ae7SKarsten Heimrich 		SetInvocationMessage(invokationMessage);
10078092ae7SKarsten Heimrich 	}
10178092ae7SKarsten Heimrich 
10278092ae7SKarsten Heimrich 	if (archive->HasMessage("_selectMsg")) {
10378092ae7SKarsten Heimrich 		BMessage* selectionMessage = new BMessage;
10478092ae7SKarsten Heimrich 		archive->FindMessage("selectMsg", selectionMessage);
10578092ae7SKarsten Heimrich 		SetSelectionMessage(selectionMessage);
10678092ae7SKarsten Heimrich 	}
10778092ae7SKarsten Heimrich 
1086846765fSOliver Tappe 	if (archive->FindInt32("_weekStart", &fStartOfWeek) != B_OK)
1096846765fSOliver Tappe 		fStartOfWeek = (int32)B_WEEKDAY_MONDAY;
11078092ae7SKarsten Heimrich 
11178092ae7SKarsten Heimrich 	if (archive->FindBool("_dayHeader", &fDayNameHeaderVisible) != B_OK)
11278092ae7SKarsten Heimrich 		fDayNameHeaderVisible = true;
11378092ae7SKarsten Heimrich 
11478092ae7SKarsten Heimrich 	if (archive->FindBool("_weekHeader", &fWeekNumberHeaderVisible) != B_OK)
11578092ae7SKarsten Heimrich 		fWeekNumberHeaderVisible = true;
11678092ae7SKarsten Heimrich 
11778092ae7SKarsten Heimrich 	_SetupDayNames();
11878092ae7SKarsten Heimrich 	_SetupDayNumbers();
11978092ae7SKarsten Heimrich 	_SetupWeekNumbers();
12078092ae7SKarsten Heimrich }
12178092ae7SKarsten Heimrich 
12278092ae7SKarsten Heimrich 
12378092ae7SKarsten Heimrich BArchivable*
12478092ae7SKarsten Heimrich BCalendarView::Instantiate(BMessage* archive)
12578092ae7SKarsten Heimrich {
12678092ae7SKarsten Heimrich 	if (validate_instantiation(archive, "BCalendarView"))
12778092ae7SKarsten Heimrich 		return new BCalendarView(archive);
12878092ae7SKarsten Heimrich 
12978092ae7SKarsten Heimrich 	return NULL;
13078092ae7SKarsten Heimrich }
13178092ae7SKarsten Heimrich 
13278092ae7SKarsten Heimrich 
13378092ae7SKarsten Heimrich status_t
13478092ae7SKarsten Heimrich BCalendarView::Archive(BMessage* archive, bool deep) const
13578092ae7SKarsten Heimrich {
13678092ae7SKarsten Heimrich 	status_t status = BView::Archive(archive, deep);
13778092ae7SKarsten Heimrich 
13878092ae7SKarsten Heimrich 	if (status == B_OK && InvocationMessage())
13978092ae7SKarsten Heimrich 		status = archive->AddMessage("_invokeMsg", InvocationMessage());
14078092ae7SKarsten Heimrich 
14178092ae7SKarsten Heimrich 	if (status == B_OK && SelectionMessage())
14278092ae7SKarsten Heimrich 		status = archive->AddMessage("_selectMsg", SelectionMessage());
14378092ae7SKarsten Heimrich 
14478092ae7SKarsten Heimrich 	if (status == B_OK)
1456846765fSOliver Tappe 		status = fDate.Archive(archive);
14678092ae7SKarsten Heimrich 
14778092ae7SKarsten Heimrich 	if (status == B_OK)
1486846765fSOliver Tappe 		status = archive->AddInt32("_weekStart", fStartOfWeek);
14978092ae7SKarsten Heimrich 
15078092ae7SKarsten Heimrich 	if (status == B_OK)
15178092ae7SKarsten Heimrich 		status = archive->AddBool("_dayHeader", fDayNameHeaderVisible);
15278092ae7SKarsten Heimrich 
15378092ae7SKarsten Heimrich 	if (status == B_OK)
15478092ae7SKarsten Heimrich 		status = archive->AddBool("_weekHeader", fWeekNumberHeaderVisible);
15578092ae7SKarsten Heimrich 
15678092ae7SKarsten Heimrich 	return status;
15778092ae7SKarsten Heimrich }
15878092ae7SKarsten Heimrich 
15978092ae7SKarsten Heimrich 
16078092ae7SKarsten Heimrich void
16178092ae7SKarsten Heimrich BCalendarView::AttachedToWindow()
16278092ae7SKarsten Heimrich {
16378092ae7SKarsten Heimrich 	BView::AttachedToWindow();
16478092ae7SKarsten Heimrich 
16578092ae7SKarsten Heimrich 	if (!Messenger().IsValid())
16678092ae7SKarsten Heimrich 		SetTarget(Window(), NULL);
16799e015b4SJanus 
168f696e88aSlooncraz 	SetViewUIColor(B_LIST_BACKGROUND_COLOR);
16978092ae7SKarsten Heimrich }
17078092ae7SKarsten Heimrich 
17178092ae7SKarsten Heimrich 
17278092ae7SKarsten Heimrich void
17378092ae7SKarsten Heimrich BCalendarView::FrameResized(float width, float height)
17478092ae7SKarsten Heimrich {
17522d88eb4SAkshay Agarwal 	_SetupDayNames();
17678092ae7SKarsten Heimrich 	Invalidate(Bounds());
17778092ae7SKarsten Heimrich }
17878092ae7SKarsten Heimrich 
17978092ae7SKarsten Heimrich 
18078092ae7SKarsten Heimrich void
18178092ae7SKarsten Heimrich BCalendarView::Draw(BRect updateRect)
18278092ae7SKarsten Heimrich {
18378092ae7SKarsten Heimrich 	if (LockLooper()) {
18478092ae7SKarsten Heimrich 		if (fFocusChanged) {
18578092ae7SKarsten Heimrich 			_DrawFocusRect();
18678092ae7SKarsten Heimrich 			UnlockLooper();
18778092ae7SKarsten Heimrich 			return;
18878092ae7SKarsten Heimrich 		}
18978092ae7SKarsten Heimrich 
19078092ae7SKarsten Heimrich 		if (fSelectionChanged) {
19178092ae7SKarsten Heimrich 			_UpdateSelection();
19278092ae7SKarsten Heimrich 			UnlockLooper();
19378092ae7SKarsten Heimrich 			return;
19478092ae7SKarsten Heimrich 		}
19578092ae7SKarsten Heimrich 
1968013f2e0SAkshay Agarwal 		if (fCurrentDayChanged) {
1978013f2e0SAkshay Agarwal 			_UpdateCurrentDay();
1988013f2e0SAkshay Agarwal 			UnlockLooper();
1998013f2e0SAkshay Agarwal 			return;
2008013f2e0SAkshay Agarwal 		}
2018013f2e0SAkshay Agarwal 
20278092ae7SKarsten Heimrich 		_DrawDays();
20378092ae7SKarsten Heimrich 		_DrawDayHeader();
20478092ae7SKarsten Heimrich 		_DrawWeekHeader();
20578092ae7SKarsten Heimrich 
20678092ae7SKarsten Heimrich 		rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
20778092ae7SKarsten Heimrich 		SetHighColor(tint_color(background, B_DARKEN_3_TINT));
20878092ae7SKarsten Heimrich 		StrokeRect(Bounds());
20978092ae7SKarsten Heimrich 
21078092ae7SKarsten Heimrich 		UnlockLooper();
21178092ae7SKarsten Heimrich 	}
21278092ae7SKarsten Heimrich }
21378092ae7SKarsten Heimrich 
21478092ae7SKarsten Heimrich 
21578092ae7SKarsten Heimrich void
21678092ae7SKarsten Heimrich BCalendarView::DrawDay(BView* owner, BRect frame, const char* text,
2178013f2e0SAkshay Agarwal 	bool isSelected, bool isEnabled, bool focus, bool highlight)
21878092ae7SKarsten Heimrich {
2198013f2e0SAkshay Agarwal 	_DrawItem(owner, frame, text, isSelected, isEnabled, focus, highlight);
22078092ae7SKarsten Heimrich }
22178092ae7SKarsten Heimrich 
22278092ae7SKarsten Heimrich 
22378092ae7SKarsten Heimrich void
22478092ae7SKarsten Heimrich BCalendarView::DrawDayName(BView* owner, BRect frame, const char* text)
22578092ae7SKarsten Heimrich {
22678092ae7SKarsten Heimrich 	// we get the full rect, fake this as the internal function
22778092ae7SKarsten Heimrich 	// shrinks the frame to work properly when drawing a day item
22878092ae7SKarsten Heimrich 	_DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true);
22978092ae7SKarsten Heimrich }
23078092ae7SKarsten Heimrich 
23178092ae7SKarsten Heimrich 
23278092ae7SKarsten Heimrich void
23378092ae7SKarsten Heimrich BCalendarView::DrawWeekNumber(BView* owner, BRect frame, const char* text)
23478092ae7SKarsten Heimrich {
23578092ae7SKarsten Heimrich 	// we get the full rect, fake this as the internal function
23678092ae7SKarsten Heimrich 	// shrinks the frame to work properly when drawing a day item
23778092ae7SKarsten Heimrich 	_DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true);
23878092ae7SKarsten Heimrich }
23978092ae7SKarsten Heimrich 
24078092ae7SKarsten Heimrich 
24178092ae7SKarsten Heimrich uint32
24278092ae7SKarsten Heimrich BCalendarView::SelectionCommand() const
24378092ae7SKarsten Heimrich {
24478092ae7SKarsten Heimrich 	if (SelectionMessage())
24578092ae7SKarsten Heimrich 		return SelectionMessage()->what;
24678092ae7SKarsten Heimrich 
24778092ae7SKarsten Heimrich 	return 0;
24878092ae7SKarsten Heimrich }
24978092ae7SKarsten Heimrich 
25078092ae7SKarsten Heimrich 
25178092ae7SKarsten Heimrich BMessage*
25278092ae7SKarsten Heimrich BCalendarView::SelectionMessage() const
25378092ae7SKarsten Heimrich {
25478092ae7SKarsten Heimrich 	return fSelectionMessage;
25578092ae7SKarsten Heimrich }
25678092ae7SKarsten Heimrich 
25778092ae7SKarsten Heimrich 
25878092ae7SKarsten Heimrich void
25978092ae7SKarsten Heimrich BCalendarView::SetSelectionMessage(BMessage* message)
26078092ae7SKarsten Heimrich {
26178092ae7SKarsten Heimrich 	delete fSelectionMessage;
26278092ae7SKarsten Heimrich 	fSelectionMessage = message;
26378092ae7SKarsten Heimrich }
26478092ae7SKarsten Heimrich 
26578092ae7SKarsten Heimrich 
26678092ae7SKarsten Heimrich uint32
26778092ae7SKarsten Heimrich BCalendarView::InvocationCommand() const
26878092ae7SKarsten Heimrich {
26978092ae7SKarsten Heimrich 	return BInvoker::Command();
27078092ae7SKarsten Heimrich }
27178092ae7SKarsten Heimrich 
27278092ae7SKarsten Heimrich 
27378092ae7SKarsten Heimrich BMessage*
27478092ae7SKarsten Heimrich BCalendarView::InvocationMessage() const
27578092ae7SKarsten Heimrich {
27678092ae7SKarsten Heimrich 	return BInvoker::Message();
27778092ae7SKarsten Heimrich }
27878092ae7SKarsten Heimrich 
27978092ae7SKarsten Heimrich 
28078092ae7SKarsten Heimrich void
28178092ae7SKarsten Heimrich BCalendarView::SetInvocationMessage(BMessage* message)
28278092ae7SKarsten Heimrich {
28378092ae7SKarsten Heimrich 	BInvoker::SetMessage(message);
28478092ae7SKarsten Heimrich }
28578092ae7SKarsten Heimrich 
28678092ae7SKarsten Heimrich 
28778092ae7SKarsten Heimrich void
28878092ae7SKarsten Heimrich BCalendarView::MakeFocus(bool state)
28978092ae7SKarsten Heimrich {
29078092ae7SKarsten Heimrich 	if (IsFocus() == state)
29178092ae7SKarsten Heimrich 		return;
29278092ae7SKarsten Heimrich 
29378092ae7SKarsten Heimrich 	BView::MakeFocus(state);
29478092ae7SKarsten Heimrich 
2951b3303e7SAxel Dörfler 	// TODO: solve this better
29678092ae7SKarsten Heimrich 	fFocusChanged = true;
29778092ae7SKarsten Heimrich 	Draw(_RectOfDay(fFocusedDay));
29878092ae7SKarsten Heimrich 	fFocusChanged = false;
29978092ae7SKarsten Heimrich }
30078092ae7SKarsten Heimrich 
30178092ae7SKarsten Heimrich 
30278092ae7SKarsten Heimrich status_t
30378092ae7SKarsten Heimrich BCalendarView::Invoke(BMessage* message)
30478092ae7SKarsten Heimrich {
30578092ae7SKarsten Heimrich 	bool notify = false;
30678092ae7SKarsten Heimrich 	uint32 kind = InvokeKind(&notify);
30778092ae7SKarsten Heimrich 
30878092ae7SKarsten Heimrich 	BMessage clone(kind);
30978092ae7SKarsten Heimrich 	status_t status = B_BAD_VALUE;
31078092ae7SKarsten Heimrich 
31178092ae7SKarsten Heimrich 	if (!message && !notify)
31278092ae7SKarsten Heimrich 		message = Message();
31378092ae7SKarsten Heimrich 
31478092ae7SKarsten Heimrich 	if (!message) {
31578092ae7SKarsten Heimrich 		if (!IsWatched())
31678092ae7SKarsten Heimrich 			return status;
31778092ae7SKarsten Heimrich 	} else
31878092ae7SKarsten Heimrich 		clone = *message;
31978092ae7SKarsten Heimrich 
32078092ae7SKarsten Heimrich 	clone.AddPointer("source", this);
32178092ae7SKarsten Heimrich 	clone.AddInt64("when", (int64)system_time());
32278092ae7SKarsten Heimrich 	clone.AddMessenger("be:sender", BMessenger(this));
32378092ae7SKarsten Heimrich 
32478092ae7SKarsten Heimrich 	int32 year;
32578092ae7SKarsten Heimrich 	int32 month;
3266846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, &month);
32778092ae7SKarsten Heimrich 
3286846765fSOliver Tappe 	clone.AddInt32("year", fDate.Year());
3296846765fSOliver Tappe 	clone.AddInt32("month", fDate.Month());
3306846765fSOliver Tappe 	clone.AddInt32("day", fDate.Day());
33178092ae7SKarsten Heimrich 
33278092ae7SKarsten Heimrich 	if (message)
33378092ae7SKarsten Heimrich 		status = BInvoker::Invoke(&clone);
33478092ae7SKarsten Heimrich 
33578092ae7SKarsten Heimrich 	SendNotices(kind, &clone);
33678092ae7SKarsten Heimrich 
33778092ae7SKarsten Heimrich 	return status;
33878092ae7SKarsten Heimrich }
33978092ae7SKarsten Heimrich 
34078092ae7SKarsten Heimrich 
34178092ae7SKarsten Heimrich void
34278092ae7SKarsten Heimrich BCalendarView::MouseDown(BPoint where)
34378092ae7SKarsten Heimrich {
34478092ae7SKarsten Heimrich 	if (!IsFocus()) {
34578092ae7SKarsten Heimrich 		MakeFocus();
34678092ae7SKarsten Heimrich 		Sync();
34778092ae7SKarsten Heimrich 		Window()->UpdateIfNeeded();
34878092ae7SKarsten Heimrich 	}
34978092ae7SKarsten Heimrich 
35078092ae7SKarsten Heimrich 	BRect frame = Bounds();
35178092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
35278092ae7SKarsten Heimrich 		frame.top += frame.Height() / 7 - 1.0;
35378092ae7SKarsten Heimrich 
35478092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible)
35578092ae7SKarsten Heimrich 		frame.left += frame.Width() / 8 - 1.0;
35678092ae7SKarsten Heimrich 
35778092ae7SKarsten Heimrich 	if (!frame.Contains(where))
35878092ae7SKarsten Heimrich 		return;
35978092ae7SKarsten Heimrich 
36078092ae7SKarsten Heimrich 	// try to set to new day
36178092ae7SKarsten Heimrich 	frame = _SetNewSelectedDay(where);
36278092ae7SKarsten Heimrich 
36378092ae7SKarsten Heimrich 	// on success
36478092ae7SKarsten Heimrich 	if (fSelectedDay != fNewSelectedDay) {
36578092ae7SKarsten Heimrich 		// update focus
36678092ae7SKarsten Heimrich 		fFocusChanged = true;
36778092ae7SKarsten Heimrich 		fNewFocusedDay = fNewSelectedDay;
36878092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
36978092ae7SKarsten Heimrich 		fFocusChanged = false;
37078092ae7SKarsten Heimrich 
37178092ae7SKarsten Heimrich 		// update selection
37278092ae7SKarsten Heimrich 		fSelectionChanged = true;
37378092ae7SKarsten Heimrich 		Draw(frame);
37478092ae7SKarsten Heimrich 		Draw(_RectOfDay(fSelectedDay));
37578092ae7SKarsten Heimrich 		fSelectionChanged = false;
37678092ae7SKarsten Heimrich 
37778092ae7SKarsten Heimrich 		// notify that selection changed
37878092ae7SKarsten Heimrich 		InvokeNotify(SelectionMessage(), B_CONTROL_MODIFIED);
37978092ae7SKarsten Heimrich 	}
38078092ae7SKarsten Heimrich 
38178092ae7SKarsten Heimrich 	int32 clicks;
38278092ae7SKarsten Heimrich 	// on double click invoke
38378092ae7SKarsten Heimrich 	BMessage* message = Looper()->CurrentMessage();
38478092ae7SKarsten Heimrich 	if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1)
38578092ae7SKarsten Heimrich 		Invoke();
38678092ae7SKarsten Heimrich }
38778092ae7SKarsten Heimrich 
38878092ae7SKarsten Heimrich 
38978092ae7SKarsten Heimrich void
39078092ae7SKarsten Heimrich BCalendarView::KeyDown(const char* bytes, int32 numBytes)
39178092ae7SKarsten Heimrich {
39278092ae7SKarsten Heimrich 	const int32 kRows = 6;
39378092ae7SKarsten Heimrich 	const int32 kColumns = 7;
39478092ae7SKarsten Heimrich 
39578092ae7SKarsten Heimrich 	int32 row = fFocusedDay.row;
39678092ae7SKarsten Heimrich 	int32 column = fFocusedDay.column;
39778092ae7SKarsten Heimrich 
39878092ae7SKarsten Heimrich 	switch (bytes[0]) {
39978092ae7SKarsten Heimrich 		case B_LEFT_ARROW:
40078092ae7SKarsten Heimrich 			column -= 1;
40178092ae7SKarsten Heimrich 			if (column < 0) {
40278092ae7SKarsten Heimrich 				column = kColumns - 1;
40378092ae7SKarsten Heimrich 				row -= 1;
40478092ae7SKarsten Heimrich 				if (row >= 0)
40578092ae7SKarsten Heimrich 					fFocusChanged = true;
40678092ae7SKarsten Heimrich 			} else
40778092ae7SKarsten Heimrich 				fFocusChanged = true;
4086846765fSOliver Tappe 			break;
40978092ae7SKarsten Heimrich 
41078092ae7SKarsten Heimrich 		case B_RIGHT_ARROW:
41178092ae7SKarsten Heimrich 			column += 1;
41278092ae7SKarsten Heimrich 			if (column == kColumns) {
41378092ae7SKarsten Heimrich 				column = 0;
41478092ae7SKarsten Heimrich 				row += 1;
41578092ae7SKarsten Heimrich 				if (row < kRows)
41678092ae7SKarsten Heimrich 					fFocusChanged = true;
41778092ae7SKarsten Heimrich 			} else
41878092ae7SKarsten Heimrich 				fFocusChanged = true;
4196846765fSOliver Tappe 			break;
42078092ae7SKarsten Heimrich 
42178092ae7SKarsten Heimrich 		case B_UP_ARROW:
42278092ae7SKarsten Heimrich 			row -= 1;
42378092ae7SKarsten Heimrich 			if (row >= 0)
42478092ae7SKarsten Heimrich 				fFocusChanged = true;
4256846765fSOliver Tappe 			break;
42678092ae7SKarsten Heimrich 
42778092ae7SKarsten Heimrich 		case B_DOWN_ARROW:
42878092ae7SKarsten Heimrich 			row += 1;
42978092ae7SKarsten Heimrich 			if (row < kRows)
43078092ae7SKarsten Heimrich 				fFocusChanged = true;
4316846765fSOliver Tappe 			break;
4326846765fSOliver Tappe 
4336846765fSOliver Tappe 		case B_PAGE_UP:
4346846765fSOliver Tappe 		{
4356846765fSOliver Tappe 			BDate date(fDate);
4366846765fSOliver Tappe 			date.AddMonths(-1);
4376846765fSOliver Tappe 			SetDate(date);
4386846765fSOliver Tappe 
4396846765fSOliver Tappe 			Invoke();
4406846765fSOliver Tappe 			break;
4416846765fSOliver Tappe 		}
4426846765fSOliver Tappe 
4436846765fSOliver Tappe 		case B_PAGE_DOWN:
4446846765fSOliver Tappe 		{
4456846765fSOliver Tappe 			BDate date(fDate);
4466846765fSOliver Tappe 			date.AddMonths(1);
4476846765fSOliver Tappe 			SetDate(date);
4486846765fSOliver Tappe 
4496846765fSOliver Tappe 			Invoke();
4506846765fSOliver Tappe 			break;
4516846765fSOliver Tappe 		}
45278092ae7SKarsten Heimrich 
45378092ae7SKarsten Heimrich 		case B_RETURN:
4546846765fSOliver Tappe 		case B_SPACE:
4556846765fSOliver Tappe 		{
45678092ae7SKarsten Heimrich 			fSelectionChanged = true;
45778092ae7SKarsten Heimrich 			BPoint pt = _RectOfDay(fFocusedDay).LeftTop();
45878092ae7SKarsten Heimrich 			Draw(_SetNewSelectedDay(pt + BPoint(4.0, 4.0)));
45978092ae7SKarsten Heimrich 			Draw(_RectOfDay(fSelectedDay));
46078092ae7SKarsten Heimrich 			fSelectionChanged = false;
46178092ae7SKarsten Heimrich 
46278092ae7SKarsten Heimrich 			Invoke();
4636846765fSOliver Tappe 			break;
4646846765fSOliver Tappe 		}
46578092ae7SKarsten Heimrich 
46678092ae7SKarsten Heimrich 		default:
46778092ae7SKarsten Heimrich 			BView::KeyDown(bytes, numBytes);
46878092ae7SKarsten Heimrich 			break;
46978092ae7SKarsten Heimrich 	}
47078092ae7SKarsten Heimrich 
47178092ae7SKarsten Heimrich 	if (fFocusChanged) {
47278092ae7SKarsten Heimrich 		fNewFocusedDay.SetTo(row, column);
47378092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
47478092ae7SKarsten Heimrich 		Draw(_RectOfDay(fNewFocusedDay));
47578092ae7SKarsten Heimrich 		fFocusChanged = false;
47678092ae7SKarsten Heimrich 	}
47778092ae7SKarsten Heimrich }
47878092ae7SKarsten Heimrich 
47978092ae7SKarsten Heimrich 
48078092ae7SKarsten Heimrich void
4818013f2e0SAkshay Agarwal BCalendarView::Pulse()
4828013f2e0SAkshay Agarwal {
4838013f2e0SAkshay Agarwal 	_UpdateCurrentDate();
4848013f2e0SAkshay Agarwal }
4858013f2e0SAkshay Agarwal 
4868013f2e0SAkshay Agarwal 
4878013f2e0SAkshay Agarwal void
48878092ae7SKarsten Heimrich BCalendarView::ResizeToPreferred()
48978092ae7SKarsten Heimrich {
49078092ae7SKarsten Heimrich 	float width;
49178092ae7SKarsten Heimrich 	float height;
49278092ae7SKarsten Heimrich 
49378092ae7SKarsten Heimrich 	GetPreferredSize(&width, &height);
49478092ae7SKarsten Heimrich 	BView::ResizeTo(width, height);
49578092ae7SKarsten Heimrich }
49678092ae7SKarsten Heimrich 
49778092ae7SKarsten Heimrich 
49878092ae7SKarsten Heimrich void
49978092ae7SKarsten Heimrich BCalendarView::GetPreferredSize(float* width, float* height)
50078092ae7SKarsten Heimrich {
50178092ae7SKarsten Heimrich 	_GetPreferredSize(width, height);
50278092ae7SKarsten Heimrich }
50378092ae7SKarsten Heimrich 
50478092ae7SKarsten Heimrich 
5052530274dSRyan Leavengood BSize
5062530274dSRyan Leavengood BCalendarView::MaxSize()
5072530274dSRyan Leavengood {
5082530274dSRyan Leavengood 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
5092530274dSRyan Leavengood 		BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
5102530274dSRyan Leavengood }
5112530274dSRyan Leavengood 
5122530274dSRyan Leavengood 
5132530274dSRyan Leavengood BSize
5142530274dSRyan Leavengood BCalendarView::MinSize()
5152530274dSRyan Leavengood {
5162530274dSRyan Leavengood 	float width, height;
5172530274dSRyan Leavengood 	_GetPreferredSize(&width, &height);
5186846765fSOliver Tappe 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(width, height));
5192530274dSRyan Leavengood }
5202530274dSRyan Leavengood 
5212530274dSRyan Leavengood 
5222530274dSRyan Leavengood BSize
5232530274dSRyan Leavengood BCalendarView::PreferredSize()
5242530274dSRyan Leavengood {
5256846765fSOliver Tappe 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
5262530274dSRyan Leavengood }
5272530274dSRyan Leavengood 
5282530274dSRyan Leavengood 
52978092ae7SKarsten Heimrich int32
53078092ae7SKarsten Heimrich BCalendarView::Day() const
53178092ae7SKarsten Heimrich {
5326846765fSOliver Tappe 	return fDate.Day();
53378092ae7SKarsten Heimrich }
53478092ae7SKarsten Heimrich 
53578092ae7SKarsten Heimrich 
53678092ae7SKarsten Heimrich int32
53778092ae7SKarsten Heimrich BCalendarView::Year() const
53878092ae7SKarsten Heimrich {
53978092ae7SKarsten Heimrich 	int32 year;
5406846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, NULL);
54178092ae7SKarsten Heimrich 
54278092ae7SKarsten Heimrich 	return year;
54378092ae7SKarsten Heimrich }
54478092ae7SKarsten Heimrich 
54578092ae7SKarsten Heimrich 
54678092ae7SKarsten Heimrich int32
54778092ae7SKarsten Heimrich BCalendarView::Month() const
54878092ae7SKarsten Heimrich {
54978092ae7SKarsten Heimrich 	int32 month;
5506846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, NULL, &month);
55178092ae7SKarsten Heimrich 
55278092ae7SKarsten Heimrich 	return month;
55378092ae7SKarsten Heimrich }
55478092ae7SKarsten Heimrich 
55578092ae7SKarsten Heimrich 
556afd5ec11SAdrien Destugues bool
557afd5ec11SAdrien Destugues BCalendarView::SetDay(int32 day)
558afd5ec11SAdrien Destugues {
559afd5ec11SAdrien Destugues 	BDate date = Date();
560afd5ec11SAdrien Destugues 	date.SetDay(day);
561afd5ec11SAdrien Destugues 	if (!date.IsValid())
562afd5ec11SAdrien Destugues 		return false;
563afd5ec11SAdrien Destugues 	SetDate(date);
564afd5ec11SAdrien Destugues 	return true;
565afd5ec11SAdrien Destugues }
566afd5ec11SAdrien Destugues 
567afd5ec11SAdrien Destugues 
568afd5ec11SAdrien Destugues bool
569afd5ec11SAdrien Destugues BCalendarView::SetMonth(int32 month)
570afd5ec11SAdrien Destugues {
571afd5ec11SAdrien Destugues 	if (month < 1 || month > 12)
572afd5ec11SAdrien Destugues 		return false;
573afd5ec11SAdrien Destugues 	BDate date = Date();
574afd5ec11SAdrien Destugues 	int32 oldDay = date.Day();
575afd5ec11SAdrien Destugues 
576afd5ec11SAdrien Destugues 	date.SetMonth(month);
577afd5ec11SAdrien Destugues 	date.SetDay(1); // make sure the date is valid
578afd5ec11SAdrien Destugues 
579afd5ec11SAdrien Destugues 	// We must make sure that the day in month fits inside the new month.
580afd5ec11SAdrien Destugues 	if (oldDay > date.DaysInMonth())
581afd5ec11SAdrien Destugues 		date.SetDay(date.DaysInMonth());
582afd5ec11SAdrien Destugues 	else
583afd5ec11SAdrien Destugues 		date.SetDay(oldDay);
584afd5ec11SAdrien Destugues 	SetDate(date);
585afd5ec11SAdrien Destugues 	return true;
586afd5ec11SAdrien Destugues }
587afd5ec11SAdrien Destugues 
588afd5ec11SAdrien Destugues 
589afd5ec11SAdrien Destugues bool
590afd5ec11SAdrien Destugues BCalendarView::SetYear(int32 year)
591afd5ec11SAdrien Destugues {
592afd5ec11SAdrien Destugues 	BDate date = Date();
593afd5ec11SAdrien Destugues 
594afd5ec11SAdrien Destugues 	// This can fail when going from 29 feb. on a leap year to a non-leap year.
595afd5ec11SAdrien Destugues 	if (date.Month() == 2 && date.Day() == 29 && !date.IsLeapYear(year))
596afd5ec11SAdrien Destugues 		date.SetDay(28);
597afd5ec11SAdrien Destugues 
598afd5ec11SAdrien Destugues 	// TODO we should also handle the "hole" at the switch between Julian and
599afd5ec11SAdrien Destugues 	// Gregorian calendars, which will result in an invalid date.
600afd5ec11SAdrien Destugues 
601afd5ec11SAdrien Destugues 	date.SetYear(year);
602afd5ec11SAdrien Destugues 	SetDate(date);
603afd5ec11SAdrien Destugues 	return true;
604afd5ec11SAdrien Destugues }
605afd5ec11SAdrien Destugues 
606afd5ec11SAdrien Destugues 
60778092ae7SKarsten Heimrich BDate
60878092ae7SKarsten Heimrich BCalendarView::Date() const
60978092ae7SKarsten Heimrich {
61078092ae7SKarsten Heimrich 	int32 year;
61178092ae7SKarsten Heimrich 	int32 month;
6126846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, &month);
6136846765fSOliver Tappe 	return BDate(year, month, fDate.Day());
61478092ae7SKarsten Heimrich }
61578092ae7SKarsten Heimrich 
61678092ae7SKarsten Heimrich 
61778092ae7SKarsten Heimrich bool
61878092ae7SKarsten Heimrich BCalendarView::SetDate(const BDate& date)
61978092ae7SKarsten Heimrich {
620c1ed5d75SKarsten Heimrich 	if (!date.IsValid())
621c1ed5d75SKarsten Heimrich 		return false;
622c1ed5d75SKarsten Heimrich 
6236846765fSOliver Tappe 	if (fDate == date)
62478092ae7SKarsten Heimrich 		return true;
62578092ae7SKarsten Heimrich 
6266846765fSOliver Tappe 	if (fDate.Year() == date.Year() && fDate.Month() == date.Month()) {
6276846765fSOliver Tappe 		fDate = date;
6286846765fSOliver Tappe 
62978092ae7SKarsten Heimrich 		_SetToDay();
63078092ae7SKarsten Heimrich 		// update focus
63178092ae7SKarsten Heimrich 		fFocusChanged = true;
63278092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
63378092ae7SKarsten Heimrich 		fFocusChanged = false;
63478092ae7SKarsten Heimrich 
63578092ae7SKarsten Heimrich 		// update selection
63678092ae7SKarsten Heimrich 		fSelectionChanged = true;
63778092ae7SKarsten Heimrich 		Draw(_RectOfDay(fSelectedDay));
63878092ae7SKarsten Heimrich 		Draw(_RectOfDay(fNewSelectedDay));
63978092ae7SKarsten Heimrich 		fSelectionChanged = false;
64078092ae7SKarsten Heimrich 	} else {
6416846765fSOliver Tappe 		fDate = date;
64278092ae7SKarsten Heimrich 
64378092ae7SKarsten Heimrich 		_SetupDayNumbers();
64478092ae7SKarsten Heimrich 		_SetupWeekNumbers();
64578092ae7SKarsten Heimrich 
64678092ae7SKarsten Heimrich 		BRect frame = Bounds();
64778092ae7SKarsten Heimrich 		if (fDayNameHeaderVisible)
64878092ae7SKarsten Heimrich 			frame.top += frame.Height() / 7 - 1.0;
64978092ae7SKarsten Heimrich 
65078092ae7SKarsten Heimrich 		if (fWeekNumberHeaderVisible)
65178092ae7SKarsten Heimrich 			frame.left += frame.Width() / 8 - 1.0;
65278092ae7SKarsten Heimrich 
65378092ae7SKarsten Heimrich 		Draw(frame.InsetBySelf(4.0, 4.0));
65478092ae7SKarsten Heimrich 	}
65578092ae7SKarsten Heimrich 
65678092ae7SKarsten Heimrich 	return true;
65778092ae7SKarsten Heimrich }
65878092ae7SKarsten Heimrich 
65978092ae7SKarsten Heimrich 
6606846765fSOliver Tappe bool
6616846765fSOliver Tappe BCalendarView::SetDate(int32 year, int32 month, int32 day)
66278092ae7SKarsten Heimrich {
6636846765fSOliver Tappe 	return SetDate(BDate(year, month, day));
6646846765fSOliver Tappe }
6656846765fSOliver Tappe 
6666846765fSOliver Tappe 
6676846765fSOliver Tappe BWeekday
6686846765fSOliver Tappe BCalendarView::StartOfWeek() const
6696846765fSOliver Tappe {
6706846765fSOliver Tappe 	return BWeekday(fStartOfWeek);
67178092ae7SKarsten Heimrich }
67278092ae7SKarsten Heimrich 
67378092ae7SKarsten Heimrich 
67478092ae7SKarsten Heimrich void
6756846765fSOliver Tappe BCalendarView::SetStartOfWeek(BWeekday startOfWeek)
67678092ae7SKarsten Heimrich {
6776846765fSOliver Tappe 	if (fStartOfWeek == (int32)startOfWeek)
67878092ae7SKarsten Heimrich 		return;
67978092ae7SKarsten Heimrich 
6806846765fSOliver Tappe 	fStartOfWeek = (int32)startOfWeek;
68178092ae7SKarsten Heimrich 
68278092ae7SKarsten Heimrich 	_SetupDayNames();
68378092ae7SKarsten Heimrich 	_SetupDayNumbers();
68478092ae7SKarsten Heimrich 	_SetupWeekNumbers();
68578092ae7SKarsten Heimrich 
68678092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
68778092ae7SKarsten Heimrich }
68878092ae7SKarsten Heimrich 
68978092ae7SKarsten Heimrich 
69078092ae7SKarsten Heimrich bool
69178092ae7SKarsten Heimrich BCalendarView::IsDayNameHeaderVisible() const
69278092ae7SKarsten Heimrich {
69378092ae7SKarsten Heimrich 	return fDayNameHeaderVisible;
69478092ae7SKarsten Heimrich }
69578092ae7SKarsten Heimrich 
69678092ae7SKarsten Heimrich 
69778092ae7SKarsten Heimrich void
69878092ae7SKarsten Heimrich BCalendarView::SetDayNameHeaderVisible(bool visible)
69978092ae7SKarsten Heimrich {
70078092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible == visible)
70178092ae7SKarsten Heimrich 		return;
70278092ae7SKarsten Heimrich 
70378092ae7SKarsten Heimrich 	fDayNameHeaderVisible = visible;
70478092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
70578092ae7SKarsten Heimrich }
70678092ae7SKarsten Heimrich 
70778092ae7SKarsten Heimrich 
70822d88eb4SAkshay Agarwal void
70922d88eb4SAkshay Agarwal BCalendarView::UpdateDayNameHeader()
71022d88eb4SAkshay Agarwal {
71122d88eb4SAkshay Agarwal 	if (!fDayNameHeaderVisible)
71222d88eb4SAkshay Agarwal 		return;
71322d88eb4SAkshay Agarwal 
71422d88eb4SAkshay Agarwal 	_SetupDayNames();
71522d88eb4SAkshay Agarwal 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
71622d88eb4SAkshay Agarwal }
71722d88eb4SAkshay Agarwal 
71822d88eb4SAkshay Agarwal 
71978092ae7SKarsten Heimrich bool
72078092ae7SKarsten Heimrich BCalendarView::IsWeekNumberHeaderVisible() const
72178092ae7SKarsten Heimrich {
72278092ae7SKarsten Heimrich 	return fWeekNumberHeaderVisible;
72378092ae7SKarsten Heimrich }
72478092ae7SKarsten Heimrich 
72578092ae7SKarsten Heimrich 
72678092ae7SKarsten Heimrich void
72778092ae7SKarsten Heimrich BCalendarView::SetWeekNumberHeaderVisible(bool visible)
72878092ae7SKarsten Heimrich {
72978092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible == visible)
73078092ae7SKarsten Heimrich 		return;
73178092ae7SKarsten Heimrich 
73278092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible = visible;
73378092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
73478092ae7SKarsten Heimrich }
73578092ae7SKarsten Heimrich 
73678092ae7SKarsten Heimrich 
73778092ae7SKarsten Heimrich void
73878092ae7SKarsten Heimrich BCalendarView::_InitObject()
73978092ae7SKarsten Heimrich {
7406846765fSOliver Tappe 	fDate = BDate::CurrentDate(B_LOCAL_TIME);
7416846765fSOliver Tappe 
7420a925409SAdrien Destugues 	BDateFormat().GetStartOfWeek((BWeekday*)&fStartOfWeek);
74378092ae7SKarsten Heimrich 
74478092ae7SKarsten Heimrich 	_SetupDayNames();
74578092ae7SKarsten Heimrich 	_SetupDayNumbers();
74678092ae7SKarsten Heimrich 	_SetupWeekNumbers();
74778092ae7SKarsten Heimrich }
74878092ae7SKarsten Heimrich 
74978092ae7SKarsten Heimrich 
75078092ae7SKarsten Heimrich void
75178092ae7SKarsten Heimrich BCalendarView::_SetToDay()
75278092ae7SKarsten Heimrich {
7536846765fSOliver Tappe 	BDate date(fDate.Year(), fDate.Month(), 1);
75478092ae7SKarsten Heimrich 	if (!date.IsValid())
75578092ae7SKarsten Heimrich 		return;
75678092ae7SKarsten Heimrich 
7576846765fSOliver Tappe 	const int32 firstDayOffset = (7 + date.DayOfWeek() - fStartOfWeek) % 7;
75878092ae7SKarsten Heimrich 
7596846765fSOliver Tappe 	int32 day = 1 - firstDayOffset;
76078092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
76178092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
7626846765fSOliver Tappe 			if (day == fDate.Day()) {
76378092ae7SKarsten Heimrich 				fNewFocusedDay.SetTo(row, column);
76478092ae7SKarsten Heimrich 				fNewSelectedDay.SetTo(row, column);
76578092ae7SKarsten Heimrich 				return;
76678092ae7SKarsten Heimrich 			}
7676846765fSOliver Tappe 			day++;
76878092ae7SKarsten Heimrich 		}
76978092ae7SKarsten Heimrich 	}
7706846765fSOliver Tappe 
7716846765fSOliver Tappe 	fNewFocusedDay.SetTo(0, 0);
7726846765fSOliver Tappe 	fNewSelectedDay.SetTo(0, 0);
77378092ae7SKarsten Heimrich }
77478092ae7SKarsten Heimrich 
77578092ae7SKarsten Heimrich 
77678092ae7SKarsten Heimrich void
7778013f2e0SAkshay Agarwal BCalendarView::_SetToCurrentDay()
7788013f2e0SAkshay Agarwal {
779b32b6a86SAkshay Agarwal 	BDate date(fCurrentDate.Year(), fCurrentDate.Month(), 1);
7808013f2e0SAkshay Agarwal 	if (!date.IsValid())
7818013f2e0SAkshay Agarwal 		return;
782b32b6a86SAkshay Agarwal 	if (fDate.Year() != date.Year() || fDate.Month() != date.Month()) {
783b32b6a86SAkshay Agarwal 		fNewCurrentDay.SetTo(-1, -1);
784b32b6a86SAkshay Agarwal 		return;
785b32b6a86SAkshay Agarwal 	}
7868013f2e0SAkshay Agarwal 	const int32 firstDayOffset = (7 + date.DayOfWeek() - fStartOfWeek) % 7;
7878013f2e0SAkshay Agarwal 
7888013f2e0SAkshay Agarwal 	int32 day = 1 - firstDayOffset;
7898013f2e0SAkshay Agarwal 	for (int32 row = 0; row < 6; ++row) {
7908013f2e0SAkshay Agarwal 		for (int32 column = 0; column < 7; ++column) {
7918013f2e0SAkshay Agarwal 			if (day == fCurrentDate.Day()) {
7928013f2e0SAkshay Agarwal 				fNewCurrentDay.SetTo(row, column);
7938013f2e0SAkshay Agarwal 				return;
7948013f2e0SAkshay Agarwal 			}
7958013f2e0SAkshay Agarwal 			day++;
7968013f2e0SAkshay Agarwal 		}
7978013f2e0SAkshay Agarwal 	}
7988013f2e0SAkshay Agarwal 
799b32b6a86SAkshay Agarwal 	fNewCurrentDay.SetTo(-1, -1);
8008013f2e0SAkshay Agarwal }
8018013f2e0SAkshay Agarwal 
8028013f2e0SAkshay Agarwal 
8038013f2e0SAkshay Agarwal void
8046846765fSOliver Tappe BCalendarView::_GetYearMonthForSelection(const Selection& selection,
8056846765fSOliver Tappe 	int32* year, int32* month) const
80678092ae7SKarsten Heimrich {
8076846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
8086846765fSOliver Tappe 	const int32 firstDayOffset
8096846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
8106846765fSOliver Tappe 	const int32 daysInMonth = startOfMonth.DaysInMonth();
81178092ae7SKarsten Heimrich 
8126846765fSOliver Tappe 	BDate date(fDate);
8136846765fSOliver Tappe 	const int32 dayOffset = selection.row * 7 + selection.column;
8146846765fSOliver Tappe 	if (dayOffset < firstDayOffset)
8156846765fSOliver Tappe 		date.AddMonths(-1);
8166846765fSOliver Tappe 	else if (dayOffset >= firstDayOffset + daysInMonth)
8176846765fSOliver Tappe 		date.AddMonths(1);
8186846765fSOliver Tappe 	if (year != NULL)
81978092ae7SKarsten Heimrich 		*year = date.Year();
8206846765fSOliver Tappe 	if (month != NULL)
82178092ae7SKarsten Heimrich 		*month = date.Month();
82278092ae7SKarsten Heimrich }
82378092ae7SKarsten Heimrich 
82478092ae7SKarsten Heimrich 
82578092ae7SKarsten Heimrich void
82678092ae7SKarsten Heimrich BCalendarView::_GetPreferredSize(float* _width, float* _height)
82778092ae7SKarsten Heimrich {
82878092ae7SKarsten Heimrich 	BFont font;
82978092ae7SKarsten Heimrich 	GetFont(&font);
83078092ae7SKarsten Heimrich 	font_height fontHeight;
83178092ae7SKarsten Heimrich 	font.GetHeight(&fontHeight);
83278092ae7SKarsten Heimrich 
83378092ae7SKarsten Heimrich 	const float height = FontHeight(this) + 4.0;
83478092ae7SKarsten Heimrich 
83578092ae7SKarsten Heimrich 	int32 rows = 7;
83678092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
83778092ae7SKarsten Heimrich 		rows = 6;
83878092ae7SKarsten Heimrich 
83978092ae7SKarsten Heimrich 	// height = font height * rows + 8 px border
84078092ae7SKarsten Heimrich 	*_height = height * rows + 8.0;
84178092ae7SKarsten Heimrich 
84278092ae7SKarsten Heimrich 	float width = 0.0;
84378092ae7SKarsten Heimrich 	for (int32 column = 0; column < 7; ++column) {
84478092ae7SKarsten Heimrich 		float tmp = StringWidth(fDayNames[column].String()) + 2.0;
84578092ae7SKarsten Heimrich 		width = tmp > width ? tmp : width;
84678092ae7SKarsten Heimrich 	}
84778092ae7SKarsten Heimrich 
84878092ae7SKarsten Heimrich 	int32 columns = 8;
84978092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
85078092ae7SKarsten Heimrich 		columns = 7;
85178092ae7SKarsten Heimrich 
85278092ae7SKarsten Heimrich 	// width = max width day name * 8 column + 8 px border
85378092ae7SKarsten Heimrich 	*_width = width * columns + 8.0;
85478092ae7SKarsten Heimrich }
85578092ae7SKarsten Heimrich 
85678092ae7SKarsten Heimrich 
85778092ae7SKarsten Heimrich void
85878092ae7SKarsten Heimrich BCalendarView::_SetupDayNames()
85978092ae7SKarsten Heimrich {
86022d88eb4SAkshay Agarwal 	BDateFormatStyle style = B_LONG_DATE_FORMAT;
86122d88eb4SAkshay Agarwal 	float width, height;
86222d88eb4SAkshay Agarwal 	while (style !=  B_DATE_FORMAT_STYLE_COUNT) {
86322d88eb4SAkshay Agarwal 		_PopulateDayNames(style);
86422d88eb4SAkshay Agarwal 		GetPreferredSize(&width, &height);
86522d88eb4SAkshay Agarwal 		if (width < Bounds().Width())
86622d88eb4SAkshay Agarwal 			return;
86722d88eb4SAkshay Agarwal 		style = static_cast<BDateFormatStyle>(static_cast<int>(style) + 1);
86822d88eb4SAkshay Agarwal 	}
86922d88eb4SAkshay Agarwal }
87022d88eb4SAkshay Agarwal 
87122d88eb4SAkshay Agarwal 
87222d88eb4SAkshay Agarwal void
87322d88eb4SAkshay Agarwal BCalendarView::_PopulateDayNames(BDateFormatStyle style)
87422d88eb4SAkshay Agarwal {
87522d88eb4SAkshay Agarwal 	for (int32 i = 0; i <= 6; ++i) {
87622d88eb4SAkshay Agarwal 		fDayNames[i] = "";
87722d88eb4SAkshay Agarwal 		BDateFormat().GetDayName(1 + (fStartOfWeek - 1 + i) % 7,
87822d88eb4SAkshay Agarwal 			fDayNames[i], style);
87922d88eb4SAkshay Agarwal 	}
88078092ae7SKarsten Heimrich }
88178092ae7SKarsten Heimrich 
88278092ae7SKarsten Heimrich 
88378092ae7SKarsten Heimrich void
88478092ae7SKarsten Heimrich BCalendarView::_SetupDayNumbers()
88578092ae7SKarsten Heimrich {
8866846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
8876846765fSOliver Tappe 	if (!startOfMonth.IsValid())
88878092ae7SKarsten Heimrich 		return;
88978092ae7SKarsten Heimrich 
89078092ae7SKarsten Heimrich 	fFocusedDay.SetTo(0, 0);
89178092ae7SKarsten Heimrich 	fSelectedDay.SetTo(0, 0);
89278092ae7SKarsten Heimrich 	fNewFocusedDay.SetTo(0, 0);
8938013f2e0SAkshay Agarwal 	fCurrentDay.SetTo(-1, -1);
89478092ae7SKarsten Heimrich 
8956846765fSOliver Tappe 	const int32 daysInMonth = startOfMonth.DaysInMonth();
8966846765fSOliver Tappe 	const int32 firstDayOffset
8976846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
89878092ae7SKarsten Heimrich 
89978092ae7SKarsten Heimrich 	// calc the last day one month before
9006846765fSOliver Tappe 	BDate lastDayInMonthBefore(startOfMonth);
9016846765fSOliver Tappe 	lastDayInMonthBefore.AddDays(-1);
9026846765fSOliver Tappe 	const int32 lastDayBefore = lastDayInMonthBefore.DaysInMonth();
90378092ae7SKarsten Heimrich 
90478092ae7SKarsten Heimrich 	int32 counter = 0;
90578092ae7SKarsten Heimrich 	int32 firstDayAfter = 1;
90678092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
90778092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
9086846765fSOliver Tappe 			int32 day = 1 + counter - firstDayOffset;
9096846765fSOliver Tappe 			if (counter < firstDayOffset)
91078092ae7SKarsten Heimrich 				day += lastDayBefore;
9116846765fSOliver Tappe 			else if (counter >= firstDayOffset + daysInMonth)
91278092ae7SKarsten Heimrich 				day = firstDayAfter++;
9136846765fSOliver Tappe 			else if (day == fDate.Day()) {
91478092ae7SKarsten Heimrich 				fFocusedDay.SetTo(row, column);
91578092ae7SKarsten Heimrich 				fSelectedDay.SetTo(row, column);
91678092ae7SKarsten Heimrich 				fNewFocusedDay.SetTo(row, column);
91778092ae7SKarsten Heimrich 			}
918b32b6a86SAkshay Agarwal 			if (day == fCurrentDate.Day() && counter >= firstDayOffset
919b32b6a86SAkshay Agarwal 				&& counter < firstDayOffset + daysInMonth
920b32b6a86SAkshay Agarwal 				&& fDate.Month() == fCurrentDate.Month()
921b32b6a86SAkshay Agarwal 				&& fDate.Year() == fCurrentDate.Year())
9228013f2e0SAkshay Agarwal 				fCurrentDay.SetTo(row, column);
923b32b6a86SAkshay Agarwal 
92478092ae7SKarsten Heimrich 			counter++;
9256846765fSOliver Tappe 			fDayNumbers[row][column].Truncate(0);
92678092ae7SKarsten Heimrich 			fDayNumbers[row][column] << day;
92778092ae7SKarsten Heimrich 		}
92878092ae7SKarsten Heimrich 	}
92978092ae7SKarsten Heimrich }
93078092ae7SKarsten Heimrich 
9316846765fSOliver Tappe 
93278092ae7SKarsten Heimrich void
93378092ae7SKarsten Heimrich BCalendarView::_SetupWeekNumbers()
93478092ae7SKarsten Heimrich {
9356846765fSOliver Tappe 	BDate date(fDate.Year(), fDate.Month(), 1);
93678092ae7SKarsten Heimrich 	if (!date.IsValid())
93778092ae7SKarsten Heimrich 		return;
93878092ae7SKarsten Heimrich 
939c1ed5d75SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
94078092ae7SKarsten Heimrich 		fWeekNumbers[row].SetTo("");
941f0932941SMichael Pfeiffer 		fWeekNumbers[row] << date.WeekNumber();
942f0932941SMichael Pfeiffer 		date.AddDays(7);
943c1ed5d75SKarsten Heimrich 	}
94478092ae7SKarsten Heimrich }
94578092ae7SKarsten Heimrich 
94678092ae7SKarsten Heimrich 
94778092ae7SKarsten Heimrich void
94887663db4SOliver Tappe BCalendarView::_DrawDay(int32 currRow, int32 currColumn, int32 row,
9498013f2e0SAkshay Agarwal 	int32 column, int32 counter, BRect frame, const char* text,
9508013f2e0SAkshay Agarwal 	bool focus, bool highlight)
95178092ae7SKarsten Heimrich {
9526846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
9536846765fSOliver Tappe 	const int32 firstDayOffset
9546846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
9556846765fSOliver Tappe 	const int32 daysMonth = startOfMonth.DaysInMonth();
95678092ae7SKarsten Heimrich 
95778092ae7SKarsten Heimrich 	bool enabled = true;
95878092ae7SKarsten Heimrich 	bool selected = false;
95978092ae7SKarsten Heimrich 	// check for the current date
96078092ae7SKarsten Heimrich 	if (currRow == row  && currColumn == column) {
96178092ae7SKarsten Heimrich 		selected = true;	// draw current date selected
9626846765fSOliver Tappe 		if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth) {
96378092ae7SKarsten Heimrich 			enabled = false;	// days of month before or after
96478092ae7SKarsten Heimrich 			selected = false;	// not selected but able to get focus
96578092ae7SKarsten Heimrich 		}
96678092ae7SKarsten Heimrich 	} else {
9676846765fSOliver Tappe 		if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth)
96878092ae7SKarsten Heimrich 			enabled = false;	// days of month before or after
96978092ae7SKarsten Heimrich 	}
97078092ae7SKarsten Heimrich 
9718013f2e0SAkshay Agarwal 	DrawDay(this, frame, text, selected, enabled, focus, highlight);
97278092ae7SKarsten Heimrich }
97378092ae7SKarsten Heimrich 
97478092ae7SKarsten Heimrich 
97578092ae7SKarsten Heimrich void
97678092ae7SKarsten Heimrich BCalendarView::_DrawDays()
97778092ae7SKarsten Heimrich {
97878092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
97978092ae7SKarsten Heimrich 
98078092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
98178092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
98278092ae7SKarsten Heimrich 
98378092ae7SKarsten Heimrich 	const bool isFocus = IsFocus();
98478092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
98578092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
98678092ae7SKarsten Heimrich 
9878013f2e0SAkshay Agarwal 	const int32 highlightRow = fCurrentDay.row;
9888013f2e0SAkshay Agarwal 	const int32 highlightColumn = fCurrentDay.column;
9898013f2e0SAkshay Agarwal 
99078092ae7SKarsten Heimrich 	int32 counter = 0;
99178092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
99278092ae7SKarsten Heimrich 		BRect tmp = frame;
99378092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
99478092ae7SKarsten Heimrich 			counter++;
99578092ae7SKarsten Heimrich 			const char* day = fDayNumbers[row][column].String();
99678092ae7SKarsten Heimrich 			bool focus = isFocus && focusRow == row && focusColumn == column;
9978013f2e0SAkshay Agarwal 			bool highlight = highlightRow == row && highlightColumn == column;
99887663db4SOliver Tappe 			_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
9998013f2e0SAkshay Agarwal 				focus, highlight);
100078092ae7SKarsten Heimrich 
100178092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
100278092ae7SKarsten Heimrich 		}
100378092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
100478092ae7SKarsten Heimrich 	}
100578092ae7SKarsten Heimrich }
100678092ae7SKarsten Heimrich 
100778092ae7SKarsten Heimrich 
100878092ae7SKarsten Heimrich void
100978092ae7SKarsten Heimrich BCalendarView::_DrawFocusRect()
101078092ae7SKarsten Heimrich {
101178092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
101278092ae7SKarsten Heimrich 
101378092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
101478092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
101578092ae7SKarsten Heimrich 
101678092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
101778092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
101878092ae7SKarsten Heimrich 
10198013f2e0SAkshay Agarwal 	const int32 highlightRow = fCurrentDay.row;
10208013f2e0SAkshay Agarwal 	const int32 highlightColumn = fCurrentDay.column;
10218013f2e0SAkshay Agarwal 
102278092ae7SKarsten Heimrich 	int32 counter = 0;
102378092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
102478092ae7SKarsten Heimrich 		BRect tmp = frame;
102578092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
102678092ae7SKarsten Heimrich 			counter++;
102778092ae7SKarsten Heimrich 			if (fNewFocusedDay.row == row && fNewFocusedDay.column == column) {
102878092ae7SKarsten Heimrich 				fFocusedDay.SetTo(row, column);
102978092ae7SKarsten Heimrich 
103078092ae7SKarsten Heimrich 				bool focus = IsFocus() && true;
10318013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
103278092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
103387663db4SOliver Tappe 				_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
10348013f2e0SAkshay Agarwal 					focus, highlight);
10356846765fSOliver Tappe 			} else if (focusRow == row && focusColumn == column) {
103678092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
10378013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
103887663db4SOliver Tappe 				_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
10398013f2e0SAkshay Agarwal 					false, highlight);
104078092ae7SKarsten Heimrich 			}
104178092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
104278092ae7SKarsten Heimrich 		}
104378092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
104478092ae7SKarsten Heimrich 	}
104578092ae7SKarsten Heimrich }
104678092ae7SKarsten Heimrich 
104778092ae7SKarsten Heimrich 
104878092ae7SKarsten Heimrich void
104978092ae7SKarsten Heimrich BCalendarView::_DrawDayHeader()
105078092ae7SKarsten Heimrich {
105178092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
105278092ae7SKarsten Heimrich 		return;
105378092ae7SKarsten Heimrich 
105478092ae7SKarsten Heimrich 	int32 offset = 1;
105578092ae7SKarsten Heimrich 	int32 columns = 8;
105678092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible) {
105778092ae7SKarsten Heimrich 		offset = 0;
105878092ae7SKarsten Heimrich 		columns = 7;
105978092ae7SKarsten Heimrich 	}
106078092ae7SKarsten Heimrich 
106178092ae7SKarsten Heimrich 	BRect frame = Bounds();
106278092ae7SKarsten Heimrich 	frame.right = frame.Width() / columns - 1.0;
106378092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / 7.0 - 2.0;
106478092ae7SKarsten Heimrich 	frame.OffsetBy(4.0, 4.0);
106578092ae7SKarsten Heimrich 
106678092ae7SKarsten Heimrich 	for (int32 i = 0; i < columns; ++i) {
106778092ae7SKarsten Heimrich 		if (i == 0 && fWeekNumberHeaderVisible) {
106878092ae7SKarsten Heimrich 			DrawDayName(this, frame, "");
106978092ae7SKarsten Heimrich 			frame.OffsetBy(frame.Width(), 0.0);
107078092ae7SKarsten Heimrich 			continue;
107178092ae7SKarsten Heimrich 		}
107278092ae7SKarsten Heimrich 		DrawDayName(this, frame, fDayNames[i - offset].String());
107378092ae7SKarsten Heimrich 		frame.OffsetBy(frame.Width(), 0.0);
107478092ae7SKarsten Heimrich 	}
107578092ae7SKarsten Heimrich }
107678092ae7SKarsten Heimrich 
107778092ae7SKarsten Heimrich 
107878092ae7SKarsten Heimrich void
107978092ae7SKarsten Heimrich BCalendarView::_DrawWeekHeader()
108078092ae7SKarsten Heimrich {
108178092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
108278092ae7SKarsten Heimrich 		return;
108378092ae7SKarsten Heimrich 
108478092ae7SKarsten Heimrich 	int32 rows = 7;
108578092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
108678092ae7SKarsten Heimrich 		rows = 6;
108778092ae7SKarsten Heimrich 
108878092ae7SKarsten Heimrich 	BRect frame = Bounds();
108978092ae7SKarsten Heimrich 	frame.right = frame.Width() / 8.0 - 2.0;
109078092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / rows - 1.0;
109178092ae7SKarsten Heimrich 
109278092ae7SKarsten Heimrich 	float offsetY = 4.0;
109378092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
109478092ae7SKarsten Heimrich 		offsetY += frame.Height();
109578092ae7SKarsten Heimrich 
109678092ae7SKarsten Heimrich 	frame.OffsetBy(4.0, offsetY);
109778092ae7SKarsten Heimrich 
109878092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
109978092ae7SKarsten Heimrich 		DrawWeekNumber(this, frame, fWeekNumbers[row].String());
110078092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
110178092ae7SKarsten Heimrich 	}
110278092ae7SKarsten Heimrich }
110378092ae7SKarsten Heimrich 
110478092ae7SKarsten Heimrich 
110578092ae7SKarsten Heimrich void
110678092ae7SKarsten Heimrich BCalendarView::_DrawItem(BView* owner, BRect frame, const char* text,
11078013f2e0SAkshay Agarwal 	bool isSelected, bool isEnabled, bool focus, bool isHighlight)
110878092ae7SKarsten Heimrich {
110978092ae7SKarsten Heimrich 	rgb_color lColor = LowColor();
111078092ae7SKarsten Heimrich 	rgb_color highColor = HighColor();
111178092ae7SKarsten Heimrich 
111299e015b4SJanus 	rgb_color textColor = ui_color(B_LIST_ITEM_TEXT_COLOR);
1113*9d30b95aSHumdinger 	rgb_color bgColor = ui_color(B_LIST_BACKGROUND_COLOR);
111499e015b4SJanus 	float tintDisabled = B_LIGHTEN_2_TINT;
1115*9d30b95aSHumdinger 	float tintHighlight = B_LIGHTEN_1_TINT;
111699e015b4SJanus 
111799e015b4SJanus 	if (textColor.red + textColor.green + textColor.blue > 125 * 3)
111899e015b4SJanus 		tintDisabled  = B_DARKEN_2_TINT;
111978092ae7SKarsten Heimrich 
1120*9d30b95aSHumdinger 	if (bgColor.red + bgColor.green + bgColor.blue > 125 * 3)
1121*9d30b95aSHumdinger 		tintHighlight = B_DARKEN_1_TINT;
1122*9d30b95aSHumdinger 
112378092ae7SKarsten Heimrich 	if (isSelected) {
112499e015b4SJanus 		SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR));
112599e015b4SJanus 		textColor = ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR);
1126*9d30b95aSHumdinger 	} else if (isHighlight)
1127*9d30b95aSHumdinger 		SetHighColor(tint_color(bgColor, tintHighlight));
1128*9d30b95aSHumdinger 	else
1129*9d30b95aSHumdinger 		SetHighColor(bgColor);
11308013f2e0SAkshay Agarwal 
113199e015b4SJanus 	SetLowColor(HighColor());
113278092ae7SKarsten Heimrich 
113378092ae7SKarsten Heimrich 	FillRect(frame.InsetByCopy(1.0, 1.0));
113478092ae7SKarsten Heimrich 
113578092ae7SKarsten Heimrich 	if (focus) {
1136*9d30b95aSHumdinger 		rgb_color focusColor = keyboard_navigation_color();
1137*9d30b95aSHumdinger 		SetHighColor(focusColor);
113878092ae7SKarsten Heimrich 		StrokeRect(frame.InsetByCopy(1.0, 1.0));
1139*9d30b95aSHumdinger 
1140*9d30b95aSHumdinger 		if (!isSelected)
1141*9d30b95aSHumdinger 			textColor = focusColor;
114278092ae7SKarsten Heimrich 	}
114378092ae7SKarsten Heimrich 
114499e015b4SJanus 	SetHighColor(textColor);
114578092ae7SKarsten Heimrich 	if (!isEnabled)
114699e015b4SJanus 		SetHighColor(tint_color(textColor, tintDisabled));
114778092ae7SKarsten Heimrich 
114878092ae7SKarsten Heimrich 	float offsetH = frame.Width() / 2.0;
11496846765fSOliver Tappe 	float offsetV = frame.Height() / 2.0 + FontHeight(owner) / 2.0 - 2.0;
115078092ae7SKarsten Heimrich 
1151*9d30b95aSHumdinger 	BFont font(be_plain_font);
1152*9d30b95aSHumdinger 	if (isHighlight)
1153*9d30b95aSHumdinger 		font.SetFace(B_BOLD_FACE);
1154*9d30b95aSHumdinger 	else
1155*9d30b95aSHumdinger 		font.SetFace(B_REGULAR_FACE);
1156*9d30b95aSHumdinger 	SetFont(&font);
1157*9d30b95aSHumdinger 
11586846765fSOliver Tappe 	DrawString(text, BPoint(frame.right - offsetH - StringWidth(text) / 2.0,
11596846765fSOliver Tappe 			frame.top + offsetV));
116078092ae7SKarsten Heimrich 
116178092ae7SKarsten Heimrich 	SetLowColor(lColor);
116278092ae7SKarsten Heimrich 	SetHighColor(highColor);
116378092ae7SKarsten Heimrich }
116478092ae7SKarsten Heimrich 
116578092ae7SKarsten Heimrich 
116678092ae7SKarsten Heimrich void
116778092ae7SKarsten Heimrich BCalendarView::_UpdateSelection()
116878092ae7SKarsten Heimrich {
116978092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
117078092ae7SKarsten Heimrich 
117178092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
117278092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
117378092ae7SKarsten Heimrich 
117478092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
117578092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
117678092ae7SKarsten Heimrich 
11778013f2e0SAkshay Agarwal 	const int32 highlightRow = fCurrentDay.row;
11788013f2e0SAkshay Agarwal 	const int32 highlightColumn = fCurrentDay.column;
11798013f2e0SAkshay Agarwal 
118078092ae7SKarsten Heimrich 	int32 counter = 0;
118178092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
118278092ae7SKarsten Heimrich 		BRect tmp = frame;
118378092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
118478092ae7SKarsten Heimrich 			counter++;
118587663db4SOliver Tappe 			if (fNewSelectedDay.row == row
118687663db4SOliver Tappe 				&& fNewSelectedDay.column == column) {
118778092ae7SKarsten Heimrich 				fSelectedDay.SetTo(row, column);
118878092ae7SKarsten Heimrich 
118978092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
119087663db4SOliver Tappe 				bool focus = IsFocus() && focusRow == row
119187663db4SOliver Tappe 					&& focusColumn == column;
11928013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
11938013f2e0SAkshay Agarwal 				_DrawDay(row, column, row, column, counter, tmp, day, focus, highlight);
11946846765fSOliver Tappe 			} else if (currRow == row && currColumn == column) {
119578092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
119687663db4SOliver Tappe 				bool focus = IsFocus() && focusRow == row
119787663db4SOliver Tappe 					&& focusColumn == column;
11988013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
11998013f2e0SAkshay Agarwal 				_DrawDay(currRow, currColumn, -1, -1, counter, tmp, day, focus, highlight);
120078092ae7SKarsten Heimrich 			}
120178092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
120278092ae7SKarsten Heimrich 		}
120378092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
120478092ae7SKarsten Heimrich 	}
120578092ae7SKarsten Heimrich }
120678092ae7SKarsten Heimrich 
120778092ae7SKarsten Heimrich 
12088013f2e0SAkshay Agarwal void
12098013f2e0SAkshay Agarwal BCalendarView::_UpdateCurrentDay()
12108013f2e0SAkshay Agarwal {
12118013f2e0SAkshay Agarwal 	BRect frame = _FirstCalendarItemFrame();
12128013f2e0SAkshay Agarwal 
12138013f2e0SAkshay Agarwal 	const int32 selectRow = fSelectedDay.row;
12148013f2e0SAkshay Agarwal 	const int32 selectColumn = fSelectedDay.column;
12158013f2e0SAkshay Agarwal 
12168013f2e0SAkshay Agarwal 	const int32 focusRow = fFocusedDay.row;
12178013f2e0SAkshay Agarwal 	const int32 focusColumn = fFocusedDay.column;
12188013f2e0SAkshay Agarwal 
12198013f2e0SAkshay Agarwal 	const int32 currRow = fCurrentDay.row;
12208013f2e0SAkshay Agarwal 	const int32 currColumn = fCurrentDay.column;
12218013f2e0SAkshay Agarwal 
12228013f2e0SAkshay Agarwal 	int32 counter = 0;
12238013f2e0SAkshay Agarwal 	for (int32 row = 0; row < 6; ++row) {
12248013f2e0SAkshay Agarwal 		BRect tmp = frame;
12258013f2e0SAkshay Agarwal 		for (int32 column = 0; column < 7; ++column) {
12268013f2e0SAkshay Agarwal 			counter++;
12278013f2e0SAkshay Agarwal 			if (fNewCurrentDay.row == row
12288013f2e0SAkshay Agarwal 				&& fNewCurrentDay.column == column) {
12298013f2e0SAkshay Agarwal 				fCurrentDay.SetTo(row, column);
12308013f2e0SAkshay Agarwal 
12318013f2e0SAkshay Agarwal 				const char* day = fDayNumbers[row][column].String();
12328013f2e0SAkshay Agarwal 				bool focus = IsFocus() && focusRow == row
12338013f2e0SAkshay Agarwal 					&& focusColumn == column;
12348013f2e0SAkshay Agarwal 				bool isSelected = selectRow == row && selectColumn == column;
12358013f2e0SAkshay Agarwal 				if (isSelected)
12368013f2e0SAkshay Agarwal 					_DrawDay(row, column, row, column, counter, tmp, day, focus, true);
12378013f2e0SAkshay Agarwal 				else
12388013f2e0SAkshay Agarwal 					_DrawDay(row, column, -1, -1, counter, tmp, day, focus, true);
12398013f2e0SAkshay Agarwal 
12408013f2e0SAkshay Agarwal 			} else if (currRow == row && currColumn == column) {
12418013f2e0SAkshay Agarwal 				const char* day = fDayNumbers[row][column].String();
12428013f2e0SAkshay Agarwal 				bool focus = IsFocus() && focusRow == row
12438013f2e0SAkshay Agarwal 					&& focusColumn == column;
12448013f2e0SAkshay Agarwal 				bool isSelected = selectRow == row && selectColumn == column;
12458013f2e0SAkshay Agarwal 				if(isSelected)
12468013f2e0SAkshay Agarwal 					_DrawDay(currRow, currColumn, row, column, counter, tmp, day, focus, false);
12478013f2e0SAkshay Agarwal 				else
12488013f2e0SAkshay Agarwal 					_DrawDay(currRow, currColumn, -1, -1, counter, tmp, day, focus, false);
12498013f2e0SAkshay Agarwal 			}
12508013f2e0SAkshay Agarwal 			tmp.OffsetBy(tmp.Width(), 0.0);
12518013f2e0SAkshay Agarwal 		}
12528013f2e0SAkshay Agarwal 		frame.OffsetBy(0.0, frame.Height());
12538013f2e0SAkshay Agarwal 	}
12548013f2e0SAkshay Agarwal }
12558013f2e0SAkshay Agarwal 
12568013f2e0SAkshay Agarwal 
12578013f2e0SAkshay Agarwal void
12588013f2e0SAkshay Agarwal BCalendarView::_UpdateCurrentDate()
12598013f2e0SAkshay Agarwal {
12608013f2e0SAkshay Agarwal 	BDate date = BDate::CurrentDate(B_LOCAL_TIME);
12618013f2e0SAkshay Agarwal 
12628013f2e0SAkshay Agarwal 	if (!date.IsValid())
12638013f2e0SAkshay Agarwal 		return;
12648013f2e0SAkshay Agarwal 	if (date == fCurrentDate)
12658013f2e0SAkshay Agarwal 		return;
12668013f2e0SAkshay Agarwal 
12678013f2e0SAkshay Agarwal 	fCurrentDate = date;
12688013f2e0SAkshay Agarwal 
12698013f2e0SAkshay Agarwal 	_SetToCurrentDay();
12708013f2e0SAkshay Agarwal 	fCurrentDayChanged = true;
12718013f2e0SAkshay Agarwal 	Draw(_RectOfDay(fCurrentDay));
12728013f2e0SAkshay Agarwal 	Draw(_RectOfDay(fNewCurrentDay));
12738013f2e0SAkshay Agarwal 	fCurrentDayChanged = false;
12748013f2e0SAkshay Agarwal 
12758013f2e0SAkshay Agarwal 	return;
12768013f2e0SAkshay Agarwal }
12778013f2e0SAkshay Agarwal 
12788013f2e0SAkshay Agarwal 
127978092ae7SKarsten Heimrich BRect
128078092ae7SKarsten Heimrich BCalendarView::_FirstCalendarItemFrame() const
128178092ae7SKarsten Heimrich {
128278092ae7SKarsten Heimrich 	int32 rows = 7;
128378092ae7SKarsten Heimrich 	int32 columns = 8;
128478092ae7SKarsten Heimrich 
128578092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
128678092ae7SKarsten Heimrich 		rows = 6;
128778092ae7SKarsten Heimrich 
128878092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
128978092ae7SKarsten Heimrich 		columns = 7;
129078092ae7SKarsten Heimrich 
129178092ae7SKarsten Heimrich 	BRect frame = Bounds();
129278092ae7SKarsten Heimrich 	frame.right = frame.Width() / columns - 1.0;
129378092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / rows - 1.0;
129478092ae7SKarsten Heimrich 
129578092ae7SKarsten Heimrich 	float offsetY = 4.0;
129678092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
129778092ae7SKarsten Heimrich 		offsetY += frame.Height();
129878092ae7SKarsten Heimrich 
129978092ae7SKarsten Heimrich 	float offsetX = 4.0;
130078092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible)
130178092ae7SKarsten Heimrich 		offsetX += frame.Width();
130278092ae7SKarsten Heimrich 
130378092ae7SKarsten Heimrich 	return frame.OffsetBySelf(offsetX, offsetY);
130478092ae7SKarsten Heimrich }
130578092ae7SKarsten Heimrich 
130678092ae7SKarsten Heimrich 
130778092ae7SKarsten Heimrich BRect
130878092ae7SKarsten Heimrich BCalendarView::_SetNewSelectedDay(const BPoint& where)
130978092ae7SKarsten Heimrich {
131078092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
131178092ae7SKarsten Heimrich 
131278092ae7SKarsten Heimrich 	int32 counter = 0;
131378092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
131478092ae7SKarsten Heimrich 		BRect tmp = frame;
131578092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
131678092ae7SKarsten Heimrich 			counter++;
131778092ae7SKarsten Heimrich 			if (tmp.Contains(where)) {
131878092ae7SKarsten Heimrich 				fNewSelectedDay.SetTo(row, column);
13196846765fSOliver Tappe 				int32 year;
13206846765fSOliver Tappe 				int32 month;
13216846765fSOliver Tappe 				_GetYearMonthForSelection(fNewSelectedDay, &year, &month);
13226846765fSOliver Tappe 				if (month == fDate.Month()) {
13236846765fSOliver Tappe 					// only change date if a day in the current month has been
13246846765fSOliver Tappe 					// selected
13256846765fSOliver Tappe 					int32 day = atoi(fDayNumbers[row][column].String());
13266846765fSOliver Tappe 					fDate.SetDate(year, month, day);
13276846765fSOliver Tappe 				}
132878092ae7SKarsten Heimrich 				return tmp;
132978092ae7SKarsten Heimrich 			}
133078092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
133178092ae7SKarsten Heimrich 		}
133278092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
133378092ae7SKarsten Heimrich 	}
133478092ae7SKarsten Heimrich 
133578092ae7SKarsten Heimrich 	return frame;
133678092ae7SKarsten Heimrich }
133778092ae7SKarsten Heimrich 
133878092ae7SKarsten Heimrich 
133978092ae7SKarsten Heimrich BRect
134078092ae7SKarsten Heimrich BCalendarView::_RectOfDay(const Selection& selection) const
134178092ae7SKarsten Heimrich {
134278092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
134378092ae7SKarsten Heimrich 
134478092ae7SKarsten Heimrich 	int32 counter = 0;
134578092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
134678092ae7SKarsten Heimrich 		BRect tmp = frame;
134778092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
134878092ae7SKarsten Heimrich 			counter++;
13496846765fSOliver Tappe 			if (selection.row == row && selection.column == column)
135078092ae7SKarsten Heimrich 				return tmp;
135178092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
135278092ae7SKarsten Heimrich 		}
135378092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
135478092ae7SKarsten Heimrich 	}
135578092ae7SKarsten Heimrich 
135678092ae7SKarsten Heimrich 	return frame;
135778092ae7SKarsten Heimrich }
135878092ae7SKarsten Heimrich 
135978092ae7SKarsten Heimrich 
136078092ae7SKarsten Heimrich }	// namespace BPrivate
1361