xref: /haiku/src/kits/shared/CalendarView.cpp (revision b32b6a8633ac957ecc34f78c124768a4735f61f6)
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(),
458013f2e0SAkshay Agarwal 	fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME)),
4678092ae7SKarsten Heimrich 	fFocusChanged(false),
4778092ae7SKarsten Heimrich 	fSelectionChanged(false),
488013f2e0SAkshay Agarwal 	fCurrentDayChanged(false),
496846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
5078092ae7SKarsten Heimrich 	fDayNameHeaderVisible(true),
5178092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible(true)
5278092ae7SKarsten Heimrich {
5378092ae7SKarsten Heimrich 	_InitObject();
5478092ae7SKarsten Heimrich }
5578092ae7SKarsten Heimrich 
5678092ae7SKarsten Heimrich 
572530274dSRyan Leavengood BCalendarView::BCalendarView(const char* name, uint32 flags)
582530274dSRyan Leavengood 	:
592530274dSRyan Leavengood 	BView(name, flags),
602530274dSRyan Leavengood 	BInvoker(),
612530274dSRyan Leavengood 	fSelectionMessage(NULL),
626846765fSOliver Tappe 	fDate(),
638013f2e0SAkshay Agarwal 	fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME)),
642530274dSRyan Leavengood 	fFocusChanged(false),
652530274dSRyan Leavengood 	fSelectionChanged(false),
668013f2e0SAkshay Agarwal 	fCurrentDayChanged(false),
676846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
681e07062bSOliver Tappe 	fDayNameHeaderVisible(true),
691e07062bSOliver Tappe 	fWeekNumberHeaderVisible(true)
701e07062bSOliver Tappe {
711e07062bSOliver Tappe 	_InitObject();
721e07062bSOliver Tappe }
731e07062bSOliver Tappe 
741e07062bSOliver Tappe 
7578092ae7SKarsten Heimrich BCalendarView::~BCalendarView()
7678092ae7SKarsten Heimrich {
7778092ae7SKarsten Heimrich 	SetSelectionMessage(NULL);
7878092ae7SKarsten Heimrich }
7978092ae7SKarsten Heimrich 
8078092ae7SKarsten Heimrich 
8178092ae7SKarsten Heimrich BCalendarView::BCalendarView(BMessage* archive)
821b3303e7SAxel Dörfler 	:
831b3303e7SAxel Dörfler 	BView(archive),
8478092ae7SKarsten Heimrich 	BInvoker(),
8578092ae7SKarsten Heimrich 	fSelectionMessage(NULL),
866846765fSOliver Tappe 	fDate(archive),
878013f2e0SAkshay Agarwal 	fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME)),
8878092ae7SKarsten Heimrich 	fFocusChanged(false),
8978092ae7SKarsten Heimrich 	fSelectionChanged(false),
908013f2e0SAkshay Agarwal 	fCurrentDayChanged(false),
916846765fSOliver Tappe 	fStartOfWeek((int32)B_WEEKDAY_MONDAY),
9278092ae7SKarsten Heimrich 	fDayNameHeaderVisible(true),
9378092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible(true)
9478092ae7SKarsten Heimrich {
9578092ae7SKarsten Heimrich 	if (archive->HasMessage("_invokeMsg")) {
9678092ae7SKarsten Heimrich 		BMessage* invokationMessage = new BMessage;
9778092ae7SKarsten Heimrich 		archive->FindMessage("_invokeMsg", invokationMessage);
9878092ae7SKarsten Heimrich 		SetInvocationMessage(invokationMessage);
9978092ae7SKarsten Heimrich 	}
10078092ae7SKarsten Heimrich 
10178092ae7SKarsten Heimrich 	if (archive->HasMessage("_selectMsg")) {
10278092ae7SKarsten Heimrich 		BMessage* selectionMessage = new BMessage;
10378092ae7SKarsten Heimrich 		archive->FindMessage("selectMsg", selectionMessage);
10478092ae7SKarsten Heimrich 		SetSelectionMessage(selectionMessage);
10578092ae7SKarsten Heimrich 	}
10678092ae7SKarsten Heimrich 
1076846765fSOliver Tappe 	if (archive->FindInt32("_weekStart", &fStartOfWeek) != B_OK)
1086846765fSOliver Tappe 		fStartOfWeek = (int32)B_WEEKDAY_MONDAY;
10978092ae7SKarsten Heimrich 
11078092ae7SKarsten Heimrich 	if (archive->FindBool("_dayHeader", &fDayNameHeaderVisible) != B_OK)
11178092ae7SKarsten Heimrich 		fDayNameHeaderVisible = true;
11278092ae7SKarsten Heimrich 
11378092ae7SKarsten Heimrich 	if (archive->FindBool("_weekHeader", &fWeekNumberHeaderVisible) != B_OK)
11478092ae7SKarsten Heimrich 		fWeekNumberHeaderVisible = true;
11578092ae7SKarsten Heimrich 
11678092ae7SKarsten Heimrich 	_SetupDayNames();
11778092ae7SKarsten Heimrich 	_SetupDayNumbers();
11878092ae7SKarsten Heimrich 	_SetupWeekNumbers();
11978092ae7SKarsten Heimrich }
12078092ae7SKarsten Heimrich 
12178092ae7SKarsten Heimrich 
12278092ae7SKarsten Heimrich BArchivable*
12378092ae7SKarsten Heimrich BCalendarView::Instantiate(BMessage* archive)
12478092ae7SKarsten Heimrich {
12578092ae7SKarsten Heimrich 	if (validate_instantiation(archive, "BCalendarView"))
12678092ae7SKarsten Heimrich 		return new BCalendarView(archive);
12778092ae7SKarsten Heimrich 
12878092ae7SKarsten Heimrich 	return NULL;
12978092ae7SKarsten Heimrich }
13078092ae7SKarsten Heimrich 
13178092ae7SKarsten Heimrich 
13278092ae7SKarsten Heimrich status_t
13378092ae7SKarsten Heimrich BCalendarView::Archive(BMessage* archive, bool deep) const
13478092ae7SKarsten Heimrich {
13578092ae7SKarsten Heimrich 	status_t status = BView::Archive(archive, deep);
13678092ae7SKarsten Heimrich 
13778092ae7SKarsten Heimrich 	if (status == B_OK && InvocationMessage())
13878092ae7SKarsten Heimrich 		status = archive->AddMessage("_invokeMsg", InvocationMessage());
13978092ae7SKarsten Heimrich 
14078092ae7SKarsten Heimrich 	if (status == B_OK && SelectionMessage())
14178092ae7SKarsten Heimrich 		status = archive->AddMessage("_selectMsg", SelectionMessage());
14278092ae7SKarsten Heimrich 
14378092ae7SKarsten Heimrich 	if (status == B_OK)
1446846765fSOliver Tappe 		status = fDate.Archive(archive);
14578092ae7SKarsten Heimrich 
14678092ae7SKarsten Heimrich 	if (status == B_OK)
1476846765fSOliver Tappe 		status = archive->AddInt32("_weekStart", fStartOfWeek);
14878092ae7SKarsten Heimrich 
14978092ae7SKarsten Heimrich 	if (status == B_OK)
15078092ae7SKarsten Heimrich 		status = archive->AddBool("_dayHeader", fDayNameHeaderVisible);
15178092ae7SKarsten Heimrich 
15278092ae7SKarsten Heimrich 	if (status == B_OK)
15378092ae7SKarsten Heimrich 		status = archive->AddBool("_weekHeader", fWeekNumberHeaderVisible);
15478092ae7SKarsten Heimrich 
15578092ae7SKarsten Heimrich 	return status;
15678092ae7SKarsten Heimrich }
15778092ae7SKarsten Heimrich 
15878092ae7SKarsten Heimrich 
15978092ae7SKarsten Heimrich void
16078092ae7SKarsten Heimrich BCalendarView::AttachedToWindow()
16178092ae7SKarsten Heimrich {
16278092ae7SKarsten Heimrich 	BView::AttachedToWindow();
16378092ae7SKarsten Heimrich 
16478092ae7SKarsten Heimrich 	if (!Messenger().IsValid())
16578092ae7SKarsten Heimrich 		SetTarget(Window(), NULL);
16699e015b4SJanus 
167f696e88aSlooncraz 	SetViewUIColor(B_LIST_BACKGROUND_COLOR);
16878092ae7SKarsten Heimrich }
16978092ae7SKarsten Heimrich 
17078092ae7SKarsten Heimrich 
17178092ae7SKarsten Heimrich void
17278092ae7SKarsten Heimrich BCalendarView::FrameResized(float width, float height)
17378092ae7SKarsten Heimrich {
17478092ae7SKarsten Heimrich 	Invalidate(Bounds());
17578092ae7SKarsten Heimrich }
17678092ae7SKarsten Heimrich 
17778092ae7SKarsten Heimrich 
17878092ae7SKarsten Heimrich void
17978092ae7SKarsten Heimrich BCalendarView::Draw(BRect updateRect)
18078092ae7SKarsten Heimrich {
18178092ae7SKarsten Heimrich 	if (LockLooper()) {
18278092ae7SKarsten Heimrich 		if (fFocusChanged) {
18378092ae7SKarsten Heimrich 			_DrawFocusRect();
18478092ae7SKarsten Heimrich 			UnlockLooper();
18578092ae7SKarsten Heimrich 			return;
18678092ae7SKarsten Heimrich 		}
18778092ae7SKarsten Heimrich 
18878092ae7SKarsten Heimrich 		if (fSelectionChanged) {
18978092ae7SKarsten Heimrich 			_UpdateSelection();
19078092ae7SKarsten Heimrich 			UnlockLooper();
19178092ae7SKarsten Heimrich 			return;
19278092ae7SKarsten Heimrich 		}
19378092ae7SKarsten Heimrich 
1948013f2e0SAkshay Agarwal 		if (fCurrentDayChanged) {
1958013f2e0SAkshay Agarwal 			_UpdateCurrentDay();
1968013f2e0SAkshay Agarwal 			UnlockLooper();
1978013f2e0SAkshay Agarwal 			return;
1988013f2e0SAkshay Agarwal 		}
1998013f2e0SAkshay Agarwal 
20078092ae7SKarsten Heimrich 		_DrawDays();
20178092ae7SKarsten Heimrich 		_DrawDayHeader();
20278092ae7SKarsten Heimrich 		_DrawWeekHeader();
20378092ae7SKarsten Heimrich 
20478092ae7SKarsten Heimrich 		rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
20578092ae7SKarsten Heimrich 		SetHighColor(tint_color(background, B_DARKEN_3_TINT));
20678092ae7SKarsten Heimrich 		StrokeRect(Bounds());
20778092ae7SKarsten Heimrich 
20878092ae7SKarsten Heimrich 		UnlockLooper();
20978092ae7SKarsten Heimrich 	}
21078092ae7SKarsten Heimrich }
21178092ae7SKarsten Heimrich 
21278092ae7SKarsten Heimrich 
21378092ae7SKarsten Heimrich void
21478092ae7SKarsten Heimrich BCalendarView::DrawDay(BView* owner, BRect frame, const char* text,
2158013f2e0SAkshay Agarwal 	bool isSelected, bool isEnabled, bool focus, bool highlight)
21678092ae7SKarsten Heimrich {
2178013f2e0SAkshay Agarwal 	_DrawItem(owner, frame, text, isSelected, isEnabled, focus, highlight);
21878092ae7SKarsten Heimrich }
21978092ae7SKarsten Heimrich 
22078092ae7SKarsten Heimrich 
22178092ae7SKarsten Heimrich void
22278092ae7SKarsten Heimrich BCalendarView::DrawDayName(BView* owner, BRect frame, const char* text)
22378092ae7SKarsten Heimrich {
22478092ae7SKarsten Heimrich 	// we get the full rect, fake this as the internal function
22578092ae7SKarsten Heimrich 	// shrinks the frame to work properly when drawing a day item
22678092ae7SKarsten Heimrich 	_DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true);
22778092ae7SKarsten Heimrich }
22878092ae7SKarsten Heimrich 
22978092ae7SKarsten Heimrich 
23078092ae7SKarsten Heimrich void
23178092ae7SKarsten Heimrich BCalendarView::DrawWeekNumber(BView* owner, BRect frame, const char* text)
23278092ae7SKarsten Heimrich {
23378092ae7SKarsten Heimrich 	// we get the full rect, fake this as the internal function
23478092ae7SKarsten Heimrich 	// shrinks the frame to work properly when drawing a day item
23578092ae7SKarsten Heimrich 	_DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true);
23678092ae7SKarsten Heimrich }
23778092ae7SKarsten Heimrich 
23878092ae7SKarsten Heimrich 
23978092ae7SKarsten Heimrich uint32
24078092ae7SKarsten Heimrich BCalendarView::SelectionCommand() const
24178092ae7SKarsten Heimrich {
24278092ae7SKarsten Heimrich 	if (SelectionMessage())
24378092ae7SKarsten Heimrich 		return SelectionMessage()->what;
24478092ae7SKarsten Heimrich 
24578092ae7SKarsten Heimrich 	return 0;
24678092ae7SKarsten Heimrich }
24778092ae7SKarsten Heimrich 
24878092ae7SKarsten Heimrich 
24978092ae7SKarsten Heimrich BMessage*
25078092ae7SKarsten Heimrich BCalendarView::SelectionMessage() const
25178092ae7SKarsten Heimrich {
25278092ae7SKarsten Heimrich 	return fSelectionMessage;
25378092ae7SKarsten Heimrich }
25478092ae7SKarsten Heimrich 
25578092ae7SKarsten Heimrich 
25678092ae7SKarsten Heimrich void
25778092ae7SKarsten Heimrich BCalendarView::SetSelectionMessage(BMessage* message)
25878092ae7SKarsten Heimrich {
25978092ae7SKarsten Heimrich 	delete fSelectionMessage;
26078092ae7SKarsten Heimrich 	fSelectionMessage = message;
26178092ae7SKarsten Heimrich }
26278092ae7SKarsten Heimrich 
26378092ae7SKarsten Heimrich 
26478092ae7SKarsten Heimrich uint32
26578092ae7SKarsten Heimrich BCalendarView::InvocationCommand() const
26678092ae7SKarsten Heimrich {
26778092ae7SKarsten Heimrich 	return BInvoker::Command();
26878092ae7SKarsten Heimrich }
26978092ae7SKarsten Heimrich 
27078092ae7SKarsten Heimrich 
27178092ae7SKarsten Heimrich BMessage*
27278092ae7SKarsten Heimrich BCalendarView::InvocationMessage() const
27378092ae7SKarsten Heimrich {
27478092ae7SKarsten Heimrich 	return BInvoker::Message();
27578092ae7SKarsten Heimrich }
27678092ae7SKarsten Heimrich 
27778092ae7SKarsten Heimrich 
27878092ae7SKarsten Heimrich void
27978092ae7SKarsten Heimrich BCalendarView::SetInvocationMessage(BMessage* message)
28078092ae7SKarsten Heimrich {
28178092ae7SKarsten Heimrich 	BInvoker::SetMessage(message);
28278092ae7SKarsten Heimrich }
28378092ae7SKarsten Heimrich 
28478092ae7SKarsten Heimrich 
28578092ae7SKarsten Heimrich void
28678092ae7SKarsten Heimrich BCalendarView::MakeFocus(bool state)
28778092ae7SKarsten Heimrich {
28878092ae7SKarsten Heimrich 	if (IsFocus() == state)
28978092ae7SKarsten Heimrich 		return;
29078092ae7SKarsten Heimrich 
29178092ae7SKarsten Heimrich 	BView::MakeFocus(state);
29278092ae7SKarsten Heimrich 
2931b3303e7SAxel Dörfler 	// TODO: solve this better
29478092ae7SKarsten Heimrich 	fFocusChanged = true;
29578092ae7SKarsten Heimrich 	Draw(_RectOfDay(fFocusedDay));
29678092ae7SKarsten Heimrich 	fFocusChanged = false;
29778092ae7SKarsten Heimrich }
29878092ae7SKarsten Heimrich 
29978092ae7SKarsten Heimrich 
30078092ae7SKarsten Heimrich status_t
30178092ae7SKarsten Heimrich BCalendarView::Invoke(BMessage* message)
30278092ae7SKarsten Heimrich {
30378092ae7SKarsten Heimrich 	bool notify = false;
30478092ae7SKarsten Heimrich 	uint32 kind = InvokeKind(&notify);
30578092ae7SKarsten Heimrich 
30678092ae7SKarsten Heimrich 	BMessage clone(kind);
30778092ae7SKarsten Heimrich 	status_t status = B_BAD_VALUE;
30878092ae7SKarsten Heimrich 
30978092ae7SKarsten Heimrich 	if (!message && !notify)
31078092ae7SKarsten Heimrich 		message = Message();
31178092ae7SKarsten Heimrich 
31278092ae7SKarsten Heimrich 	if (!message) {
31378092ae7SKarsten Heimrich 		if (!IsWatched())
31478092ae7SKarsten Heimrich 			return status;
31578092ae7SKarsten Heimrich 	} else
31678092ae7SKarsten Heimrich 		clone = *message;
31778092ae7SKarsten Heimrich 
31878092ae7SKarsten Heimrich 	clone.AddPointer("source", this);
31978092ae7SKarsten Heimrich 	clone.AddInt64("when", (int64)system_time());
32078092ae7SKarsten Heimrich 	clone.AddMessenger("be:sender", BMessenger(this));
32178092ae7SKarsten Heimrich 
32278092ae7SKarsten Heimrich 	int32 year;
32378092ae7SKarsten Heimrich 	int32 month;
3246846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, &month);
32578092ae7SKarsten Heimrich 
3266846765fSOliver Tappe 	clone.AddInt32("year", fDate.Year());
3276846765fSOliver Tappe 	clone.AddInt32("month", fDate.Month());
3286846765fSOliver Tappe 	clone.AddInt32("day", fDate.Day());
32978092ae7SKarsten Heimrich 
33078092ae7SKarsten Heimrich 	if (message)
33178092ae7SKarsten Heimrich 		status = BInvoker::Invoke(&clone);
33278092ae7SKarsten Heimrich 
33378092ae7SKarsten Heimrich 	SendNotices(kind, &clone);
33478092ae7SKarsten Heimrich 
33578092ae7SKarsten Heimrich 	return status;
33678092ae7SKarsten Heimrich }
33778092ae7SKarsten Heimrich 
33878092ae7SKarsten Heimrich 
33978092ae7SKarsten Heimrich void
34078092ae7SKarsten Heimrich BCalendarView::MouseDown(BPoint where)
34178092ae7SKarsten Heimrich {
34278092ae7SKarsten Heimrich 	if (!IsFocus()) {
34378092ae7SKarsten Heimrich 		MakeFocus();
34478092ae7SKarsten Heimrich 		Sync();
34578092ae7SKarsten Heimrich 		Window()->UpdateIfNeeded();
34678092ae7SKarsten Heimrich 	}
34778092ae7SKarsten Heimrich 
34878092ae7SKarsten Heimrich 	BRect frame = Bounds();
34978092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
35078092ae7SKarsten Heimrich 		frame.top += frame.Height() / 7 - 1.0;
35178092ae7SKarsten Heimrich 
35278092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible)
35378092ae7SKarsten Heimrich 		frame.left += frame.Width() / 8 - 1.0;
35478092ae7SKarsten Heimrich 
35578092ae7SKarsten Heimrich 	if (!frame.Contains(where))
35678092ae7SKarsten Heimrich 		return;
35778092ae7SKarsten Heimrich 
35878092ae7SKarsten Heimrich 	// try to set to new day
35978092ae7SKarsten Heimrich 	frame = _SetNewSelectedDay(where);
36078092ae7SKarsten Heimrich 
36178092ae7SKarsten Heimrich 	// on success
36278092ae7SKarsten Heimrich 	if (fSelectedDay != fNewSelectedDay) {
36378092ae7SKarsten Heimrich 		// update focus
36478092ae7SKarsten Heimrich 		fFocusChanged = true;
36578092ae7SKarsten Heimrich 		fNewFocusedDay = fNewSelectedDay;
36678092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
36778092ae7SKarsten Heimrich 		fFocusChanged = false;
36878092ae7SKarsten Heimrich 
36978092ae7SKarsten Heimrich 		// update selection
37078092ae7SKarsten Heimrich 		fSelectionChanged = true;
37178092ae7SKarsten Heimrich 		Draw(frame);
37278092ae7SKarsten Heimrich 		Draw(_RectOfDay(fSelectedDay));
37378092ae7SKarsten Heimrich 		fSelectionChanged = false;
37478092ae7SKarsten Heimrich 
37578092ae7SKarsten Heimrich 		// notify that selection changed
37678092ae7SKarsten Heimrich 		InvokeNotify(SelectionMessage(), B_CONTROL_MODIFIED);
37778092ae7SKarsten Heimrich 	}
37878092ae7SKarsten Heimrich 
37978092ae7SKarsten Heimrich 	int32 clicks;
38078092ae7SKarsten Heimrich 	// on double click invoke
38178092ae7SKarsten Heimrich 	BMessage* message = Looper()->CurrentMessage();
38278092ae7SKarsten Heimrich 	if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1)
38378092ae7SKarsten Heimrich 		Invoke();
38478092ae7SKarsten Heimrich }
38578092ae7SKarsten Heimrich 
38678092ae7SKarsten Heimrich 
38778092ae7SKarsten Heimrich void
38878092ae7SKarsten Heimrich BCalendarView::KeyDown(const char* bytes, int32 numBytes)
38978092ae7SKarsten Heimrich {
39078092ae7SKarsten Heimrich 	const int32 kRows = 6;
39178092ae7SKarsten Heimrich 	const int32 kColumns = 7;
39278092ae7SKarsten Heimrich 
39378092ae7SKarsten Heimrich 	int32 row = fFocusedDay.row;
39478092ae7SKarsten Heimrich 	int32 column = fFocusedDay.column;
39578092ae7SKarsten Heimrich 
39678092ae7SKarsten Heimrich 	switch (bytes[0]) {
39778092ae7SKarsten Heimrich 		case B_LEFT_ARROW:
39878092ae7SKarsten Heimrich 			column -= 1;
39978092ae7SKarsten Heimrich 			if (column < 0) {
40078092ae7SKarsten Heimrich 				column = kColumns - 1;
40178092ae7SKarsten Heimrich 				row -= 1;
40278092ae7SKarsten Heimrich 				if (row >= 0)
40378092ae7SKarsten Heimrich 					fFocusChanged = true;
40478092ae7SKarsten Heimrich 			} else
40578092ae7SKarsten Heimrich 				fFocusChanged = true;
4066846765fSOliver Tappe 			break;
40778092ae7SKarsten Heimrich 
40878092ae7SKarsten Heimrich 		case B_RIGHT_ARROW:
40978092ae7SKarsten Heimrich 			column += 1;
41078092ae7SKarsten Heimrich 			if (column == kColumns) {
41178092ae7SKarsten Heimrich 				column = 0;
41278092ae7SKarsten Heimrich 				row += 1;
41378092ae7SKarsten Heimrich 				if (row < kRows)
41478092ae7SKarsten Heimrich 					fFocusChanged = true;
41578092ae7SKarsten Heimrich 			} else
41678092ae7SKarsten Heimrich 				fFocusChanged = true;
4176846765fSOliver Tappe 			break;
41878092ae7SKarsten Heimrich 
41978092ae7SKarsten Heimrich 		case B_UP_ARROW:
42078092ae7SKarsten Heimrich 			row -= 1;
42178092ae7SKarsten Heimrich 			if (row >= 0)
42278092ae7SKarsten Heimrich 				fFocusChanged = true;
4236846765fSOliver Tappe 			break;
42478092ae7SKarsten Heimrich 
42578092ae7SKarsten Heimrich 		case B_DOWN_ARROW:
42678092ae7SKarsten Heimrich 			row += 1;
42778092ae7SKarsten Heimrich 			if (row < kRows)
42878092ae7SKarsten Heimrich 				fFocusChanged = true;
4296846765fSOliver Tappe 			break;
4306846765fSOliver Tappe 
4316846765fSOliver Tappe 		case B_PAGE_UP:
4326846765fSOliver Tappe 		{
4336846765fSOliver Tappe 			BDate date(fDate);
4346846765fSOliver Tappe 			date.AddMonths(-1);
4356846765fSOliver Tappe 			SetDate(date);
4366846765fSOliver Tappe 
4376846765fSOliver Tappe 			Invoke();
4386846765fSOliver Tappe 			break;
4396846765fSOliver Tappe 		}
4406846765fSOliver Tappe 
4416846765fSOliver Tappe 		case B_PAGE_DOWN:
4426846765fSOliver Tappe 		{
4436846765fSOliver Tappe 			BDate date(fDate);
4446846765fSOliver Tappe 			date.AddMonths(1);
4456846765fSOliver Tappe 			SetDate(date);
4466846765fSOliver Tappe 
4476846765fSOliver Tappe 			Invoke();
4486846765fSOliver Tappe 			break;
4496846765fSOliver Tappe 		}
45078092ae7SKarsten Heimrich 
45178092ae7SKarsten Heimrich 		case B_RETURN:
4526846765fSOliver Tappe 		case B_SPACE:
4536846765fSOliver Tappe 		{
45478092ae7SKarsten Heimrich 			fSelectionChanged = true;
45578092ae7SKarsten Heimrich 			BPoint pt = _RectOfDay(fFocusedDay).LeftTop();
45678092ae7SKarsten Heimrich 			Draw(_SetNewSelectedDay(pt + BPoint(4.0, 4.0)));
45778092ae7SKarsten Heimrich 			Draw(_RectOfDay(fSelectedDay));
45878092ae7SKarsten Heimrich 			fSelectionChanged = false;
45978092ae7SKarsten Heimrich 
46078092ae7SKarsten Heimrich 			Invoke();
4616846765fSOliver Tappe 			break;
4626846765fSOliver Tappe 		}
46378092ae7SKarsten Heimrich 
46478092ae7SKarsten Heimrich 		default:
46578092ae7SKarsten Heimrich 			BView::KeyDown(bytes, numBytes);
46678092ae7SKarsten Heimrich 			break;
46778092ae7SKarsten Heimrich 	}
46878092ae7SKarsten Heimrich 
46978092ae7SKarsten Heimrich 	if (fFocusChanged) {
47078092ae7SKarsten Heimrich 		fNewFocusedDay.SetTo(row, column);
47178092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
47278092ae7SKarsten Heimrich 		Draw(_RectOfDay(fNewFocusedDay));
47378092ae7SKarsten Heimrich 		fFocusChanged = false;
47478092ae7SKarsten Heimrich 	}
47578092ae7SKarsten Heimrich }
47678092ae7SKarsten Heimrich 
47778092ae7SKarsten Heimrich 
47878092ae7SKarsten Heimrich void
4798013f2e0SAkshay Agarwal BCalendarView::Pulse()
4808013f2e0SAkshay Agarwal {
4818013f2e0SAkshay Agarwal 	_UpdateCurrentDate();
4828013f2e0SAkshay Agarwal }
4838013f2e0SAkshay Agarwal 
4848013f2e0SAkshay Agarwal 
4858013f2e0SAkshay Agarwal void
48678092ae7SKarsten Heimrich BCalendarView::ResizeToPreferred()
48778092ae7SKarsten Heimrich {
48878092ae7SKarsten Heimrich 	float width;
48978092ae7SKarsten Heimrich 	float height;
49078092ae7SKarsten Heimrich 
49178092ae7SKarsten Heimrich 	GetPreferredSize(&width, &height);
49278092ae7SKarsten Heimrich 	BView::ResizeTo(width, height);
49378092ae7SKarsten Heimrich }
49478092ae7SKarsten Heimrich 
49578092ae7SKarsten Heimrich 
49678092ae7SKarsten Heimrich void
49778092ae7SKarsten Heimrich BCalendarView::GetPreferredSize(float* width, float* height)
49878092ae7SKarsten Heimrich {
49978092ae7SKarsten Heimrich 	_GetPreferredSize(width, height);
50078092ae7SKarsten Heimrich }
50178092ae7SKarsten Heimrich 
50278092ae7SKarsten Heimrich 
5032530274dSRyan Leavengood BSize
5042530274dSRyan Leavengood BCalendarView::MaxSize()
5052530274dSRyan Leavengood {
5062530274dSRyan Leavengood 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
5072530274dSRyan Leavengood 		BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
5082530274dSRyan Leavengood }
5092530274dSRyan Leavengood 
5102530274dSRyan Leavengood 
5112530274dSRyan Leavengood BSize
5122530274dSRyan Leavengood BCalendarView::MinSize()
5132530274dSRyan Leavengood {
5142530274dSRyan Leavengood 	float width, height;
5152530274dSRyan Leavengood 	_GetPreferredSize(&width, &height);
5166846765fSOliver Tappe 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(width, height));
5172530274dSRyan Leavengood }
5182530274dSRyan Leavengood 
5192530274dSRyan Leavengood 
5202530274dSRyan Leavengood BSize
5212530274dSRyan Leavengood BCalendarView::PreferredSize()
5222530274dSRyan Leavengood {
5236846765fSOliver Tappe 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
5242530274dSRyan Leavengood }
5252530274dSRyan Leavengood 
5262530274dSRyan Leavengood 
52778092ae7SKarsten Heimrich int32
52878092ae7SKarsten Heimrich BCalendarView::Day() const
52978092ae7SKarsten Heimrich {
5306846765fSOliver Tappe 	return fDate.Day();
53178092ae7SKarsten Heimrich }
53278092ae7SKarsten Heimrich 
53378092ae7SKarsten Heimrich 
53478092ae7SKarsten Heimrich int32
53578092ae7SKarsten Heimrich BCalendarView::Year() const
53678092ae7SKarsten Heimrich {
53778092ae7SKarsten Heimrich 	int32 year;
5386846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, NULL);
53978092ae7SKarsten Heimrich 
54078092ae7SKarsten Heimrich 	return year;
54178092ae7SKarsten Heimrich }
54278092ae7SKarsten Heimrich 
54378092ae7SKarsten Heimrich 
54478092ae7SKarsten Heimrich int32
54578092ae7SKarsten Heimrich BCalendarView::Month() const
54678092ae7SKarsten Heimrich {
54778092ae7SKarsten Heimrich 	int32 month;
5486846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, NULL, &month);
54978092ae7SKarsten Heimrich 
55078092ae7SKarsten Heimrich 	return month;
55178092ae7SKarsten Heimrich }
55278092ae7SKarsten Heimrich 
55378092ae7SKarsten Heimrich 
554afd5ec11SAdrien Destugues bool
555afd5ec11SAdrien Destugues BCalendarView::SetDay(int32 day)
556afd5ec11SAdrien Destugues {
557afd5ec11SAdrien Destugues 	BDate date = Date();
558afd5ec11SAdrien Destugues 	date.SetDay(day);
559afd5ec11SAdrien Destugues 	if (!date.IsValid())
560afd5ec11SAdrien Destugues 		return false;
561afd5ec11SAdrien Destugues 	SetDate(date);
562afd5ec11SAdrien Destugues 	return true;
563afd5ec11SAdrien Destugues }
564afd5ec11SAdrien Destugues 
565afd5ec11SAdrien Destugues 
566afd5ec11SAdrien Destugues bool
567afd5ec11SAdrien Destugues BCalendarView::SetMonth(int32 month)
568afd5ec11SAdrien Destugues {
569afd5ec11SAdrien Destugues 	if (month < 1 || month > 12)
570afd5ec11SAdrien Destugues 		return false;
571afd5ec11SAdrien Destugues 	BDate date = Date();
572afd5ec11SAdrien Destugues 	int32 oldDay = date.Day();
573afd5ec11SAdrien Destugues 
574afd5ec11SAdrien Destugues 	date.SetMonth(month);
575afd5ec11SAdrien Destugues 	date.SetDay(1); // make sure the date is valid
576afd5ec11SAdrien Destugues 
577afd5ec11SAdrien Destugues 	// We must make sure that the day in month fits inside the new month.
578afd5ec11SAdrien Destugues 	if (oldDay > date.DaysInMonth())
579afd5ec11SAdrien Destugues 		date.SetDay(date.DaysInMonth());
580afd5ec11SAdrien Destugues 	else
581afd5ec11SAdrien Destugues 		date.SetDay(oldDay);
582afd5ec11SAdrien Destugues 	SetDate(date);
583afd5ec11SAdrien Destugues 	return true;
584afd5ec11SAdrien Destugues }
585afd5ec11SAdrien Destugues 
586afd5ec11SAdrien Destugues 
587afd5ec11SAdrien Destugues bool
588afd5ec11SAdrien Destugues BCalendarView::SetYear(int32 year)
589afd5ec11SAdrien Destugues {
590afd5ec11SAdrien Destugues 	BDate date = Date();
591afd5ec11SAdrien Destugues 
592afd5ec11SAdrien Destugues 	// This can fail when going from 29 feb. on a leap year to a non-leap year.
593afd5ec11SAdrien Destugues 	if (date.Month() == 2 && date.Day() == 29 && !date.IsLeapYear(year))
594afd5ec11SAdrien Destugues 		date.SetDay(28);
595afd5ec11SAdrien Destugues 
596afd5ec11SAdrien Destugues 	// TODO we should also handle the "hole" at the switch between Julian and
597afd5ec11SAdrien Destugues 	// Gregorian calendars, which will result in an invalid date.
598afd5ec11SAdrien Destugues 
599afd5ec11SAdrien Destugues 	date.SetYear(year);
600afd5ec11SAdrien Destugues 	SetDate(date);
601afd5ec11SAdrien Destugues 	return true;
602afd5ec11SAdrien Destugues }
603afd5ec11SAdrien Destugues 
604afd5ec11SAdrien Destugues 
60578092ae7SKarsten Heimrich BDate
60678092ae7SKarsten Heimrich BCalendarView::Date() const
60778092ae7SKarsten Heimrich {
60878092ae7SKarsten Heimrich 	int32 year;
60978092ae7SKarsten Heimrich 	int32 month;
6106846765fSOliver Tappe 	_GetYearMonthForSelection(fSelectedDay, &year, &month);
6116846765fSOliver Tappe 	return BDate(year, month, fDate.Day());
61278092ae7SKarsten Heimrich }
61378092ae7SKarsten Heimrich 
61478092ae7SKarsten Heimrich 
61578092ae7SKarsten Heimrich bool
61678092ae7SKarsten Heimrich BCalendarView::SetDate(const BDate& date)
61778092ae7SKarsten Heimrich {
618c1ed5d75SKarsten Heimrich 	if (!date.IsValid())
619c1ed5d75SKarsten Heimrich 		return false;
620c1ed5d75SKarsten Heimrich 
6216846765fSOliver Tappe 	if (fDate == date)
62278092ae7SKarsten Heimrich 		return true;
62378092ae7SKarsten Heimrich 
6246846765fSOliver Tappe 	if (fDate.Year() == date.Year() && fDate.Month() == date.Month()) {
6256846765fSOliver Tappe 		fDate = date;
6266846765fSOliver Tappe 
62778092ae7SKarsten Heimrich 		_SetToDay();
62878092ae7SKarsten Heimrich 		// update focus
62978092ae7SKarsten Heimrich 		fFocusChanged = true;
63078092ae7SKarsten Heimrich 		Draw(_RectOfDay(fFocusedDay));
63178092ae7SKarsten Heimrich 		fFocusChanged = false;
63278092ae7SKarsten Heimrich 
63378092ae7SKarsten Heimrich 		// update selection
63478092ae7SKarsten Heimrich 		fSelectionChanged = true;
63578092ae7SKarsten Heimrich 		Draw(_RectOfDay(fSelectedDay));
63678092ae7SKarsten Heimrich 		Draw(_RectOfDay(fNewSelectedDay));
63778092ae7SKarsten Heimrich 		fSelectionChanged = false;
63878092ae7SKarsten Heimrich 	} else {
6396846765fSOliver Tappe 		fDate = date;
64078092ae7SKarsten Heimrich 
64178092ae7SKarsten Heimrich 		_SetupDayNumbers();
64278092ae7SKarsten Heimrich 		_SetupWeekNumbers();
64378092ae7SKarsten Heimrich 
64478092ae7SKarsten Heimrich 		BRect frame = Bounds();
64578092ae7SKarsten Heimrich 		if (fDayNameHeaderVisible)
64678092ae7SKarsten Heimrich 			frame.top += frame.Height() / 7 - 1.0;
64778092ae7SKarsten Heimrich 
64878092ae7SKarsten Heimrich 		if (fWeekNumberHeaderVisible)
64978092ae7SKarsten Heimrich 			frame.left += frame.Width() / 8 - 1.0;
65078092ae7SKarsten Heimrich 
65178092ae7SKarsten Heimrich 		Draw(frame.InsetBySelf(4.0, 4.0));
65278092ae7SKarsten Heimrich 	}
65378092ae7SKarsten Heimrich 
65478092ae7SKarsten Heimrich 	return true;
65578092ae7SKarsten Heimrich }
65678092ae7SKarsten Heimrich 
65778092ae7SKarsten Heimrich 
6586846765fSOliver Tappe bool
6596846765fSOliver Tappe BCalendarView::SetDate(int32 year, int32 month, int32 day)
66078092ae7SKarsten Heimrich {
6616846765fSOliver Tappe 	return SetDate(BDate(year, month, day));
6626846765fSOliver Tappe }
6636846765fSOliver Tappe 
6646846765fSOliver Tappe 
6656846765fSOliver Tappe BWeekday
6666846765fSOliver Tappe BCalendarView::StartOfWeek() const
6676846765fSOliver Tappe {
6686846765fSOliver Tappe 	return BWeekday(fStartOfWeek);
66978092ae7SKarsten Heimrich }
67078092ae7SKarsten Heimrich 
67178092ae7SKarsten Heimrich 
67278092ae7SKarsten Heimrich void
6736846765fSOliver Tappe BCalendarView::SetStartOfWeek(BWeekday startOfWeek)
67478092ae7SKarsten Heimrich {
6756846765fSOliver Tappe 	if (fStartOfWeek == (int32)startOfWeek)
67678092ae7SKarsten Heimrich 		return;
67778092ae7SKarsten Heimrich 
6786846765fSOliver Tappe 	fStartOfWeek = (int32)startOfWeek;
67978092ae7SKarsten Heimrich 
68078092ae7SKarsten Heimrich 	_SetupDayNames();
68178092ae7SKarsten Heimrich 	_SetupDayNumbers();
68278092ae7SKarsten Heimrich 	_SetupWeekNumbers();
68378092ae7SKarsten Heimrich 
68478092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
68578092ae7SKarsten Heimrich }
68678092ae7SKarsten Heimrich 
68778092ae7SKarsten Heimrich 
68878092ae7SKarsten Heimrich bool
68978092ae7SKarsten Heimrich BCalendarView::IsDayNameHeaderVisible() const
69078092ae7SKarsten Heimrich {
69178092ae7SKarsten Heimrich 	return fDayNameHeaderVisible;
69278092ae7SKarsten Heimrich }
69378092ae7SKarsten Heimrich 
69478092ae7SKarsten Heimrich 
69578092ae7SKarsten Heimrich void
69678092ae7SKarsten Heimrich BCalendarView::SetDayNameHeaderVisible(bool visible)
69778092ae7SKarsten Heimrich {
69878092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible == visible)
69978092ae7SKarsten Heimrich 		return;
70078092ae7SKarsten Heimrich 
70178092ae7SKarsten Heimrich 	fDayNameHeaderVisible = visible;
70278092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
70378092ae7SKarsten Heimrich }
70478092ae7SKarsten Heimrich 
70578092ae7SKarsten Heimrich 
70678092ae7SKarsten Heimrich bool
70778092ae7SKarsten Heimrich BCalendarView::IsWeekNumberHeaderVisible() const
70878092ae7SKarsten Heimrich {
70978092ae7SKarsten Heimrich 	return fWeekNumberHeaderVisible;
71078092ae7SKarsten Heimrich }
71178092ae7SKarsten Heimrich 
71278092ae7SKarsten Heimrich 
71378092ae7SKarsten Heimrich void
71478092ae7SKarsten Heimrich BCalendarView::SetWeekNumberHeaderVisible(bool visible)
71578092ae7SKarsten Heimrich {
71678092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible == visible)
71778092ae7SKarsten Heimrich 		return;
71878092ae7SKarsten Heimrich 
71978092ae7SKarsten Heimrich 	fWeekNumberHeaderVisible = visible;
72078092ae7SKarsten Heimrich 	Invalidate(Bounds().InsetBySelf(1.0, 1.0));
72178092ae7SKarsten Heimrich }
72278092ae7SKarsten Heimrich 
72378092ae7SKarsten Heimrich 
72478092ae7SKarsten Heimrich void
72578092ae7SKarsten Heimrich BCalendarView::_InitObject()
72678092ae7SKarsten Heimrich {
7276846765fSOliver Tappe 	fDate = BDate::CurrentDate(B_LOCAL_TIME);
7286846765fSOliver Tappe 
7290a925409SAdrien Destugues 	BDateFormat().GetStartOfWeek((BWeekday*)&fStartOfWeek);
73078092ae7SKarsten Heimrich 
73178092ae7SKarsten Heimrich 	_SetupDayNames();
73278092ae7SKarsten Heimrich 	_SetupDayNumbers();
73378092ae7SKarsten Heimrich 	_SetupWeekNumbers();
73478092ae7SKarsten Heimrich }
73578092ae7SKarsten Heimrich 
73678092ae7SKarsten Heimrich 
73778092ae7SKarsten Heimrich void
73878092ae7SKarsten Heimrich BCalendarView::_SetToDay()
73978092ae7SKarsten Heimrich {
7406846765fSOliver Tappe 	BDate date(fDate.Year(), fDate.Month(), 1);
74178092ae7SKarsten Heimrich 	if (!date.IsValid())
74278092ae7SKarsten Heimrich 		return;
74378092ae7SKarsten Heimrich 
7446846765fSOliver Tappe 	const int32 firstDayOffset = (7 + date.DayOfWeek() - fStartOfWeek) % 7;
74578092ae7SKarsten Heimrich 
7466846765fSOliver Tappe 	int32 day = 1 - firstDayOffset;
74778092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
74878092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
7496846765fSOliver Tappe 			if (day == fDate.Day()) {
75078092ae7SKarsten Heimrich 				fNewFocusedDay.SetTo(row, column);
75178092ae7SKarsten Heimrich 				fNewSelectedDay.SetTo(row, column);
75278092ae7SKarsten Heimrich 				return;
75378092ae7SKarsten Heimrich 			}
7546846765fSOliver Tappe 			day++;
75578092ae7SKarsten Heimrich 		}
75678092ae7SKarsten Heimrich 	}
7576846765fSOliver Tappe 
7586846765fSOliver Tappe 	fNewFocusedDay.SetTo(0, 0);
7596846765fSOliver Tappe 	fNewSelectedDay.SetTo(0, 0);
76078092ae7SKarsten Heimrich }
76178092ae7SKarsten Heimrich 
76278092ae7SKarsten Heimrich 
76378092ae7SKarsten Heimrich void
7648013f2e0SAkshay Agarwal BCalendarView::_SetToCurrentDay()
7658013f2e0SAkshay Agarwal {
766*b32b6a86SAkshay Agarwal 	BDate date(fCurrentDate.Year(), fCurrentDate.Month(), 1);
7678013f2e0SAkshay Agarwal 	if (!date.IsValid())
7688013f2e0SAkshay Agarwal 		return;
769*b32b6a86SAkshay Agarwal 	if (fDate.Year() != date.Year() || fDate.Month() != date.Month()) {
770*b32b6a86SAkshay Agarwal 		fNewCurrentDay.SetTo(-1, -1);
771*b32b6a86SAkshay Agarwal 		return;
772*b32b6a86SAkshay Agarwal 	}
7738013f2e0SAkshay Agarwal 	const int32 firstDayOffset = (7 + date.DayOfWeek() - fStartOfWeek) % 7;
7748013f2e0SAkshay Agarwal 
7758013f2e0SAkshay Agarwal 	int32 day = 1 - firstDayOffset;
7768013f2e0SAkshay Agarwal 	for (int32 row = 0; row < 6; ++row) {
7778013f2e0SAkshay Agarwal 		for (int32 column = 0; column < 7; ++column) {
7788013f2e0SAkshay Agarwal 			if (day == fCurrentDate.Day()) {
7798013f2e0SAkshay Agarwal 				fNewCurrentDay.SetTo(row, column);
7808013f2e0SAkshay Agarwal 				return;
7818013f2e0SAkshay Agarwal 			}
7828013f2e0SAkshay Agarwal 			day++;
7838013f2e0SAkshay Agarwal 		}
7848013f2e0SAkshay Agarwal 	}
7858013f2e0SAkshay Agarwal 
786*b32b6a86SAkshay Agarwal 	fNewCurrentDay.SetTo(-1, -1);
7878013f2e0SAkshay Agarwal }
7888013f2e0SAkshay Agarwal 
7898013f2e0SAkshay Agarwal 
7908013f2e0SAkshay Agarwal void
7916846765fSOliver Tappe BCalendarView::_GetYearMonthForSelection(const Selection& selection,
7926846765fSOliver Tappe 	int32* year, int32* month) const
79378092ae7SKarsten Heimrich {
7946846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
7956846765fSOliver Tappe 	const int32 firstDayOffset
7966846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
7976846765fSOliver Tappe 	const int32 daysInMonth = startOfMonth.DaysInMonth();
79878092ae7SKarsten Heimrich 
7996846765fSOliver Tappe 	BDate date(fDate);
8006846765fSOliver Tappe 	const int32 dayOffset = selection.row * 7 + selection.column;
8016846765fSOliver Tappe 	if (dayOffset < firstDayOffset)
8026846765fSOliver Tappe 		date.AddMonths(-1);
8036846765fSOliver Tappe 	else if (dayOffset >= firstDayOffset + daysInMonth)
8046846765fSOliver Tappe 		date.AddMonths(1);
8056846765fSOliver Tappe 	if (year != NULL)
80678092ae7SKarsten Heimrich 		*year = date.Year();
8076846765fSOliver Tappe 	if (month != NULL)
80878092ae7SKarsten Heimrich 		*month = date.Month();
80978092ae7SKarsten Heimrich }
81078092ae7SKarsten Heimrich 
81178092ae7SKarsten Heimrich 
81278092ae7SKarsten Heimrich void
81378092ae7SKarsten Heimrich BCalendarView::_GetPreferredSize(float* _width, float* _height)
81478092ae7SKarsten Heimrich {
81578092ae7SKarsten Heimrich 	BFont font;
81678092ae7SKarsten Heimrich 	GetFont(&font);
81778092ae7SKarsten Heimrich 	font_height fontHeight;
81878092ae7SKarsten Heimrich 	font.GetHeight(&fontHeight);
81978092ae7SKarsten Heimrich 
82078092ae7SKarsten Heimrich 	const float height = FontHeight(this) + 4.0;
82178092ae7SKarsten Heimrich 
82278092ae7SKarsten Heimrich 	int32 rows = 7;
82378092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
82478092ae7SKarsten Heimrich 		rows = 6;
82578092ae7SKarsten Heimrich 
82678092ae7SKarsten Heimrich 	// height = font height * rows + 8 px border
82778092ae7SKarsten Heimrich 	*_height = height * rows + 8.0;
82878092ae7SKarsten Heimrich 
82978092ae7SKarsten Heimrich 	float width = 0.0;
83078092ae7SKarsten Heimrich 	for (int32 column = 0; column < 7; ++column) {
83178092ae7SKarsten Heimrich 		float tmp = StringWidth(fDayNames[column].String()) + 2.0;
83278092ae7SKarsten Heimrich 		width = tmp > width ? tmp : width;
83378092ae7SKarsten Heimrich 	}
83478092ae7SKarsten Heimrich 
83578092ae7SKarsten Heimrich 	int32 columns = 8;
83678092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
83778092ae7SKarsten Heimrich 		columns = 7;
83878092ae7SKarsten Heimrich 
83978092ae7SKarsten Heimrich 	// width = max width day name * 8 column + 8 px border
84078092ae7SKarsten Heimrich 	*_width = width * columns + 8.0;
84178092ae7SKarsten Heimrich }
84278092ae7SKarsten Heimrich 
84378092ae7SKarsten Heimrich 
84478092ae7SKarsten Heimrich void
84578092ae7SKarsten Heimrich BCalendarView::_SetupDayNames()
84678092ae7SKarsten Heimrich {
8476846765fSOliver Tappe 	for (int32 i = 0; i <= 6; ++i)
8486846765fSOliver Tappe 		fDayNames[i] = fDate.ShortDayName(1 + (fStartOfWeek - 1 + i) % 7);
84978092ae7SKarsten Heimrich }
85078092ae7SKarsten Heimrich 
85178092ae7SKarsten Heimrich 
85278092ae7SKarsten Heimrich void
85378092ae7SKarsten Heimrich BCalendarView::_SetupDayNumbers()
85478092ae7SKarsten Heimrich {
8556846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
8566846765fSOliver Tappe 	if (!startOfMonth.IsValid())
85778092ae7SKarsten Heimrich 		return;
85878092ae7SKarsten Heimrich 
85978092ae7SKarsten Heimrich 	fFocusedDay.SetTo(0, 0);
86078092ae7SKarsten Heimrich 	fSelectedDay.SetTo(0, 0);
86178092ae7SKarsten Heimrich 	fNewFocusedDay.SetTo(0, 0);
8628013f2e0SAkshay Agarwal 	fCurrentDay.SetTo(-1, -1);
86378092ae7SKarsten Heimrich 
8646846765fSOliver Tappe 	const int32 daysInMonth = startOfMonth.DaysInMonth();
8656846765fSOliver Tappe 	const int32 firstDayOffset
8666846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
86778092ae7SKarsten Heimrich 
86878092ae7SKarsten Heimrich 	// calc the last day one month before
8696846765fSOliver Tappe 	BDate lastDayInMonthBefore(startOfMonth);
8706846765fSOliver Tappe 	lastDayInMonthBefore.AddDays(-1);
8716846765fSOliver Tappe 	const int32 lastDayBefore = lastDayInMonthBefore.DaysInMonth();
87278092ae7SKarsten Heimrich 
87378092ae7SKarsten Heimrich 	int32 counter = 0;
87478092ae7SKarsten Heimrich 	int32 firstDayAfter = 1;
87578092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
87678092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
8776846765fSOliver Tappe 			int32 day = 1 + counter - firstDayOffset;
8786846765fSOliver Tappe 			if (counter < firstDayOffset)
87978092ae7SKarsten Heimrich 				day += lastDayBefore;
8806846765fSOliver Tappe 			else if (counter >= firstDayOffset + daysInMonth)
88178092ae7SKarsten Heimrich 				day = firstDayAfter++;
8826846765fSOliver Tappe 			else if (day == fDate.Day()) {
88378092ae7SKarsten Heimrich 				fFocusedDay.SetTo(row, column);
88478092ae7SKarsten Heimrich 				fSelectedDay.SetTo(row, column);
88578092ae7SKarsten Heimrich 				fNewFocusedDay.SetTo(row, column);
88678092ae7SKarsten Heimrich 			}
887*b32b6a86SAkshay Agarwal 			if (day == fCurrentDate.Day() && counter >= firstDayOffset
888*b32b6a86SAkshay Agarwal 				&& counter < firstDayOffset + daysInMonth
889*b32b6a86SAkshay Agarwal 				&& fDate.Month() == fCurrentDate.Month()
890*b32b6a86SAkshay Agarwal 				&& fDate.Year() == fCurrentDate.Year())
8918013f2e0SAkshay Agarwal 				fCurrentDay.SetTo(row, column);
892*b32b6a86SAkshay Agarwal 
89378092ae7SKarsten Heimrich 			counter++;
8946846765fSOliver Tappe 			fDayNumbers[row][column].Truncate(0);
89578092ae7SKarsten Heimrich 			fDayNumbers[row][column] << day;
89678092ae7SKarsten Heimrich 		}
89778092ae7SKarsten Heimrich 	}
89878092ae7SKarsten Heimrich }
89978092ae7SKarsten Heimrich 
9006846765fSOliver Tappe 
90178092ae7SKarsten Heimrich void
90278092ae7SKarsten Heimrich BCalendarView::_SetupWeekNumbers()
90378092ae7SKarsten Heimrich {
9046846765fSOliver Tappe 	BDate date(fDate.Year(), fDate.Month(), 1);
90578092ae7SKarsten Heimrich 	if (!date.IsValid())
90678092ae7SKarsten Heimrich 		return;
90778092ae7SKarsten Heimrich 
908c1ed5d75SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
90978092ae7SKarsten Heimrich 		fWeekNumbers[row].SetTo("");
910f0932941SMichael Pfeiffer 		fWeekNumbers[row] << date.WeekNumber();
911f0932941SMichael Pfeiffer 		date.AddDays(7);
912c1ed5d75SKarsten Heimrich 	}
91378092ae7SKarsten Heimrich }
91478092ae7SKarsten Heimrich 
91578092ae7SKarsten Heimrich 
91678092ae7SKarsten Heimrich void
91787663db4SOliver Tappe BCalendarView::_DrawDay(int32 currRow, int32 currColumn, int32 row,
9188013f2e0SAkshay Agarwal 	int32 column, int32 counter, BRect frame, const char* text,
9198013f2e0SAkshay Agarwal 	bool focus, bool highlight)
92078092ae7SKarsten Heimrich {
9216846765fSOliver Tappe 	BDate startOfMonth(fDate.Year(), fDate.Month(), 1);
9226846765fSOliver Tappe 	const int32 firstDayOffset
9236846765fSOliver Tappe 		= (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7;
9246846765fSOliver Tappe 	const int32 daysMonth = startOfMonth.DaysInMonth();
92578092ae7SKarsten Heimrich 
92678092ae7SKarsten Heimrich 	bool enabled = true;
92778092ae7SKarsten Heimrich 	bool selected = false;
92878092ae7SKarsten Heimrich 	// check for the current date
92978092ae7SKarsten Heimrich 	if (currRow == row  && currColumn == column) {
93078092ae7SKarsten Heimrich 		selected = true;	// draw current date selected
9316846765fSOliver Tappe 		if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth) {
93278092ae7SKarsten Heimrich 			enabled = false;	// days of month before or after
93378092ae7SKarsten Heimrich 			selected = false;	// not selected but able to get focus
93478092ae7SKarsten Heimrich 		}
93578092ae7SKarsten Heimrich 	} else {
9366846765fSOliver Tappe 		if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth)
93778092ae7SKarsten Heimrich 			enabled = false;	// days of month before or after
93878092ae7SKarsten Heimrich 	}
93978092ae7SKarsten Heimrich 
9408013f2e0SAkshay Agarwal 	DrawDay(this, frame, text, selected, enabled, focus, highlight);
94178092ae7SKarsten Heimrich }
94278092ae7SKarsten Heimrich 
94378092ae7SKarsten Heimrich 
94478092ae7SKarsten Heimrich void
94578092ae7SKarsten Heimrich BCalendarView::_DrawDays()
94678092ae7SKarsten Heimrich {
94778092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
94878092ae7SKarsten Heimrich 
94978092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
95078092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
95178092ae7SKarsten Heimrich 
95278092ae7SKarsten Heimrich 	const bool isFocus = IsFocus();
95378092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
95478092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
95578092ae7SKarsten Heimrich 
9568013f2e0SAkshay Agarwal 	const int32 highlightRow = fCurrentDay.row;
9578013f2e0SAkshay Agarwal 	const int32 highlightColumn = fCurrentDay.column;
9588013f2e0SAkshay Agarwal 
95978092ae7SKarsten Heimrich 	int32 counter = 0;
96078092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
96178092ae7SKarsten Heimrich 		BRect tmp = frame;
96278092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
96378092ae7SKarsten Heimrich 			counter++;
96478092ae7SKarsten Heimrich 			const char* day = fDayNumbers[row][column].String();
96578092ae7SKarsten Heimrich 			bool focus = isFocus && focusRow == row && focusColumn == column;
9668013f2e0SAkshay Agarwal 			bool highlight = highlightRow == row && highlightColumn == column;
96787663db4SOliver Tappe 			_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
9688013f2e0SAkshay Agarwal 				focus, highlight);
96978092ae7SKarsten Heimrich 
97078092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
97178092ae7SKarsten Heimrich 		}
97278092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
97378092ae7SKarsten Heimrich 	}
97478092ae7SKarsten Heimrich }
97578092ae7SKarsten Heimrich 
97678092ae7SKarsten Heimrich 
97778092ae7SKarsten Heimrich void
97878092ae7SKarsten Heimrich BCalendarView::_DrawFocusRect()
97978092ae7SKarsten Heimrich {
98078092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
98178092ae7SKarsten Heimrich 
98278092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
98378092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
98478092ae7SKarsten Heimrich 
98578092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
98678092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
98778092ae7SKarsten Heimrich 
9888013f2e0SAkshay Agarwal 	const int32 highlightRow = fCurrentDay.row;
9898013f2e0SAkshay Agarwal 	const int32 highlightColumn = fCurrentDay.column;
9908013f2e0SAkshay Agarwal 
99178092ae7SKarsten Heimrich 	int32 counter = 0;
99278092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
99378092ae7SKarsten Heimrich 		BRect tmp = frame;
99478092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
99578092ae7SKarsten Heimrich 			counter++;
99678092ae7SKarsten Heimrich 			if (fNewFocusedDay.row == row && fNewFocusedDay.column == column) {
99778092ae7SKarsten Heimrich 				fFocusedDay.SetTo(row, column);
99878092ae7SKarsten Heimrich 
99978092ae7SKarsten Heimrich 				bool focus = IsFocus() && true;
10008013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
100178092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
100287663db4SOliver Tappe 				_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
10038013f2e0SAkshay Agarwal 					focus, highlight);
10046846765fSOliver Tappe 			} else if (focusRow == row && focusColumn == column) {
100578092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
10068013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
100787663db4SOliver Tappe 				_DrawDay(currRow, currColumn, row, column, counter, tmp, day,
10088013f2e0SAkshay Agarwal 					false, highlight);
100978092ae7SKarsten Heimrich 			}
101078092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
101178092ae7SKarsten Heimrich 		}
101278092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
101378092ae7SKarsten Heimrich 	}
101478092ae7SKarsten Heimrich }
101578092ae7SKarsten Heimrich 
101678092ae7SKarsten Heimrich 
101778092ae7SKarsten Heimrich void
101878092ae7SKarsten Heimrich BCalendarView::_DrawDayHeader()
101978092ae7SKarsten Heimrich {
102078092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
102178092ae7SKarsten Heimrich 		return;
102278092ae7SKarsten Heimrich 
102378092ae7SKarsten Heimrich 	int32 offset = 1;
102478092ae7SKarsten Heimrich 	int32 columns = 8;
102578092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible) {
102678092ae7SKarsten Heimrich 		offset = 0;
102778092ae7SKarsten Heimrich 		columns = 7;
102878092ae7SKarsten Heimrich 	}
102978092ae7SKarsten Heimrich 
103078092ae7SKarsten Heimrich 	BRect frame = Bounds();
103178092ae7SKarsten Heimrich 	frame.right = frame.Width() / columns - 1.0;
103278092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / 7.0 - 2.0;
103378092ae7SKarsten Heimrich 	frame.OffsetBy(4.0, 4.0);
103478092ae7SKarsten Heimrich 
103578092ae7SKarsten Heimrich 	for (int32 i = 0; i < columns; ++i) {
103678092ae7SKarsten Heimrich 		if (i == 0 && fWeekNumberHeaderVisible) {
103778092ae7SKarsten Heimrich 			DrawDayName(this, frame, "");
103878092ae7SKarsten Heimrich 			frame.OffsetBy(frame.Width(), 0.0);
103978092ae7SKarsten Heimrich 			continue;
104078092ae7SKarsten Heimrich 		}
104178092ae7SKarsten Heimrich 		DrawDayName(this, frame, fDayNames[i - offset].String());
104278092ae7SKarsten Heimrich 		frame.OffsetBy(frame.Width(), 0.0);
104378092ae7SKarsten Heimrich 	}
104478092ae7SKarsten Heimrich }
104578092ae7SKarsten Heimrich 
104678092ae7SKarsten Heimrich 
104778092ae7SKarsten Heimrich void
104878092ae7SKarsten Heimrich BCalendarView::_DrawWeekHeader()
104978092ae7SKarsten Heimrich {
105078092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
105178092ae7SKarsten Heimrich 		return;
105278092ae7SKarsten Heimrich 
105378092ae7SKarsten Heimrich 	int32 rows = 7;
105478092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
105578092ae7SKarsten Heimrich 		rows = 6;
105678092ae7SKarsten Heimrich 
105778092ae7SKarsten Heimrich 	BRect frame = Bounds();
105878092ae7SKarsten Heimrich 	frame.right = frame.Width() / 8.0 - 2.0;
105978092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / rows - 1.0;
106078092ae7SKarsten Heimrich 
106178092ae7SKarsten Heimrich 	float offsetY = 4.0;
106278092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
106378092ae7SKarsten Heimrich 		offsetY += frame.Height();
106478092ae7SKarsten Heimrich 
106578092ae7SKarsten Heimrich 	frame.OffsetBy(4.0, offsetY);
106678092ae7SKarsten Heimrich 
106778092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
106878092ae7SKarsten Heimrich 		DrawWeekNumber(this, frame, fWeekNumbers[row].String());
106978092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
107078092ae7SKarsten Heimrich 	}
107178092ae7SKarsten Heimrich }
107278092ae7SKarsten Heimrich 
107378092ae7SKarsten Heimrich 
107478092ae7SKarsten Heimrich void
107578092ae7SKarsten Heimrich BCalendarView::_DrawItem(BView* owner, BRect frame, const char* text,
10768013f2e0SAkshay Agarwal 	bool isSelected, bool isEnabled, bool focus, bool isHighlight)
107778092ae7SKarsten Heimrich {
107878092ae7SKarsten Heimrich 	rgb_color lColor = LowColor();
107978092ae7SKarsten Heimrich 	rgb_color highColor = HighColor();
108078092ae7SKarsten Heimrich 
108199e015b4SJanus 	rgb_color textColor = ui_color(B_LIST_ITEM_TEXT_COLOR);
108299e015b4SJanus 	float tintDisabled = B_LIGHTEN_2_TINT;
108399e015b4SJanus 
108499e015b4SJanus 	if (textColor.red + textColor.green + textColor.blue > 125 * 3)
108599e015b4SJanus 		tintDisabled  = B_DARKEN_2_TINT;
108678092ae7SKarsten Heimrich 
108778092ae7SKarsten Heimrich 	if (isSelected) {
108899e015b4SJanus 		SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR));
108999e015b4SJanus 		textColor = ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR);
109078092ae7SKarsten Heimrich 	} else
109199e015b4SJanus 		SetHighColor(ui_color(B_LIST_BACKGROUND_COLOR));
109299e015b4SJanus 
10938013f2e0SAkshay Agarwal 	if (isHighlight) {
10948013f2e0SAkshay Agarwal 		textColor = keyboard_navigation_color();
10958013f2e0SAkshay Agarwal 	}
10968013f2e0SAkshay Agarwal 
109799e015b4SJanus 	SetLowColor(HighColor());
109878092ae7SKarsten Heimrich 
109978092ae7SKarsten Heimrich 	FillRect(frame.InsetByCopy(1.0, 1.0));
110078092ae7SKarsten Heimrich 
110178092ae7SKarsten Heimrich 	if (focus) {
110278092ae7SKarsten Heimrich 		SetHighColor(keyboard_navigation_color());
110378092ae7SKarsten Heimrich 		StrokeRect(frame.InsetByCopy(1.0, 1.0));
110478092ae7SKarsten Heimrich 	}
110578092ae7SKarsten Heimrich 
110699e015b4SJanus 	SetHighColor(textColor);
110778092ae7SKarsten Heimrich 	if (!isEnabled)
110899e015b4SJanus 		SetHighColor(tint_color(textColor, tintDisabled));
110978092ae7SKarsten Heimrich 
111078092ae7SKarsten Heimrich 	float offsetH = frame.Width() / 2.0;
11116846765fSOliver Tappe 	float offsetV = frame.Height() / 2.0 + FontHeight(owner) / 2.0 - 2.0;
111278092ae7SKarsten Heimrich 
11136846765fSOliver Tappe 	DrawString(text, BPoint(frame.right - offsetH - StringWidth(text) / 2.0,
11146846765fSOliver Tappe 			frame.top + offsetV));
111578092ae7SKarsten Heimrich 
111678092ae7SKarsten Heimrich 	SetLowColor(lColor);
111778092ae7SKarsten Heimrich 	SetHighColor(highColor);
111878092ae7SKarsten Heimrich }
111978092ae7SKarsten Heimrich 
112078092ae7SKarsten Heimrich 
112178092ae7SKarsten Heimrich void
112278092ae7SKarsten Heimrich BCalendarView::_UpdateSelection()
112378092ae7SKarsten Heimrich {
112478092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
112578092ae7SKarsten Heimrich 
112678092ae7SKarsten Heimrich 	const int32 currRow = fSelectedDay.row;
112778092ae7SKarsten Heimrich 	const int32 currColumn = fSelectedDay.column;
112878092ae7SKarsten Heimrich 
112978092ae7SKarsten Heimrich 	const int32 focusRow = fFocusedDay.row;
113078092ae7SKarsten Heimrich 	const int32 focusColumn = fFocusedDay.column;
113178092ae7SKarsten Heimrich 
11328013f2e0SAkshay Agarwal 	const int32 highlightRow = fCurrentDay.row;
11338013f2e0SAkshay Agarwal 	const int32 highlightColumn = fCurrentDay.column;
11348013f2e0SAkshay Agarwal 
113578092ae7SKarsten Heimrich 	int32 counter = 0;
113678092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
113778092ae7SKarsten Heimrich 		BRect tmp = frame;
113878092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
113978092ae7SKarsten Heimrich 			counter++;
114087663db4SOliver Tappe 			if (fNewSelectedDay.row == row
114187663db4SOliver Tappe 				&& fNewSelectedDay.column == column) {
114278092ae7SKarsten Heimrich 				fSelectedDay.SetTo(row, column);
114378092ae7SKarsten Heimrich 
114478092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
114587663db4SOliver Tappe 				bool focus = IsFocus() && focusRow == row
114687663db4SOliver Tappe 					&& focusColumn == column;
11478013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
11488013f2e0SAkshay Agarwal 				_DrawDay(row, column, row, column, counter, tmp, day, focus, highlight);
11496846765fSOliver Tappe 			} else if (currRow == row && currColumn == column) {
115078092ae7SKarsten Heimrich 				const char* day = fDayNumbers[row][column].String();
115187663db4SOliver Tappe 				bool focus = IsFocus() && focusRow == row
115287663db4SOliver Tappe 					&& focusColumn == column;
11538013f2e0SAkshay Agarwal 				bool highlight = highlightRow == row && highlightColumn == column;
11548013f2e0SAkshay Agarwal 				_DrawDay(currRow, currColumn, -1, -1, counter, tmp, day, focus, highlight);
115578092ae7SKarsten Heimrich 			}
115678092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
115778092ae7SKarsten Heimrich 		}
115878092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
115978092ae7SKarsten Heimrich 	}
116078092ae7SKarsten Heimrich }
116178092ae7SKarsten Heimrich 
116278092ae7SKarsten Heimrich 
11638013f2e0SAkshay Agarwal void
11648013f2e0SAkshay Agarwal BCalendarView::_UpdateCurrentDay()
11658013f2e0SAkshay Agarwal {
11668013f2e0SAkshay Agarwal 	BRect frame = _FirstCalendarItemFrame();
11678013f2e0SAkshay Agarwal 
11688013f2e0SAkshay Agarwal 	const int32 selectRow = fSelectedDay.row;
11698013f2e0SAkshay Agarwal 	const int32 selectColumn = fSelectedDay.column;
11708013f2e0SAkshay Agarwal 
11718013f2e0SAkshay Agarwal 	const int32 focusRow = fFocusedDay.row;
11728013f2e0SAkshay Agarwal 	const int32 focusColumn = fFocusedDay.column;
11738013f2e0SAkshay Agarwal 
11748013f2e0SAkshay Agarwal 	const int32 currRow = fCurrentDay.row;
11758013f2e0SAkshay Agarwal 	const int32 currColumn = fCurrentDay.column;
11768013f2e0SAkshay Agarwal 
11778013f2e0SAkshay Agarwal 	int32 counter = 0;
11788013f2e0SAkshay Agarwal 	for (int32 row = 0; row < 6; ++row) {
11798013f2e0SAkshay Agarwal 		BRect tmp = frame;
11808013f2e0SAkshay Agarwal 		for (int32 column = 0; column < 7; ++column) {
11818013f2e0SAkshay Agarwal 			counter++;
11828013f2e0SAkshay Agarwal 			if (fNewCurrentDay.row == row
11838013f2e0SAkshay Agarwal 				&& fNewCurrentDay.column == column) {
11848013f2e0SAkshay Agarwal 				fCurrentDay.SetTo(row, column);
11858013f2e0SAkshay Agarwal 
11868013f2e0SAkshay Agarwal 				const char* day = fDayNumbers[row][column].String();
11878013f2e0SAkshay Agarwal 				bool focus = IsFocus() && focusRow == row
11888013f2e0SAkshay Agarwal 					&& focusColumn == column;
11898013f2e0SAkshay Agarwal 				bool isSelected = selectRow == row && selectColumn == column;
11908013f2e0SAkshay Agarwal 				if (isSelected)
11918013f2e0SAkshay Agarwal 					_DrawDay(row, column, row, column, counter, tmp, day, focus, true);
11928013f2e0SAkshay Agarwal 				else
11938013f2e0SAkshay Agarwal 					_DrawDay(row, column, -1, -1, counter, tmp, day, focus, true);
11948013f2e0SAkshay Agarwal 
11958013f2e0SAkshay Agarwal 			} else if (currRow == row && currColumn == column) {
11968013f2e0SAkshay Agarwal 				const char* day = fDayNumbers[row][column].String();
11978013f2e0SAkshay Agarwal 				bool focus = IsFocus() && focusRow == row
11988013f2e0SAkshay Agarwal 					&& focusColumn == column;
11998013f2e0SAkshay Agarwal 				bool isSelected = selectRow == row && selectColumn == column;
12008013f2e0SAkshay Agarwal 				if(isSelected)
12018013f2e0SAkshay Agarwal 					_DrawDay(currRow, currColumn, row, column, counter, tmp, day, focus, false);
12028013f2e0SAkshay Agarwal 				else
12038013f2e0SAkshay Agarwal 					_DrawDay(currRow, currColumn, -1, -1, counter, tmp, day, focus, false);
12048013f2e0SAkshay Agarwal 			}
12058013f2e0SAkshay Agarwal 			tmp.OffsetBy(tmp.Width(), 0.0);
12068013f2e0SAkshay Agarwal 		}
12078013f2e0SAkshay Agarwal 		frame.OffsetBy(0.0, frame.Height());
12088013f2e0SAkshay Agarwal 	}
12098013f2e0SAkshay Agarwal }
12108013f2e0SAkshay Agarwal 
12118013f2e0SAkshay Agarwal 
12128013f2e0SAkshay Agarwal void
12138013f2e0SAkshay Agarwal BCalendarView::_UpdateCurrentDate()
12148013f2e0SAkshay Agarwal {
12158013f2e0SAkshay Agarwal 	BDate date = BDate::CurrentDate(B_LOCAL_TIME);
12168013f2e0SAkshay Agarwal 
12178013f2e0SAkshay Agarwal 	if (!date.IsValid())
12188013f2e0SAkshay Agarwal 		return;
12198013f2e0SAkshay Agarwal 	if (date == fCurrentDate)
12208013f2e0SAkshay Agarwal 		return;
12218013f2e0SAkshay Agarwal 
12228013f2e0SAkshay Agarwal 	fCurrentDate = date;
12238013f2e0SAkshay Agarwal 
12248013f2e0SAkshay Agarwal 	_SetToCurrentDay();
12258013f2e0SAkshay Agarwal 	fCurrentDayChanged = true;
12268013f2e0SAkshay Agarwal 	Draw(_RectOfDay(fCurrentDay));
12278013f2e0SAkshay Agarwal 	Draw(_RectOfDay(fNewCurrentDay));
12288013f2e0SAkshay Agarwal 	fCurrentDayChanged = false;
12298013f2e0SAkshay Agarwal 
12308013f2e0SAkshay Agarwal 	return;
12318013f2e0SAkshay Agarwal }
12328013f2e0SAkshay Agarwal 
12338013f2e0SAkshay Agarwal 
123478092ae7SKarsten Heimrich BRect
123578092ae7SKarsten Heimrich BCalendarView::_FirstCalendarItemFrame() const
123678092ae7SKarsten Heimrich {
123778092ae7SKarsten Heimrich 	int32 rows = 7;
123878092ae7SKarsten Heimrich 	int32 columns = 8;
123978092ae7SKarsten Heimrich 
124078092ae7SKarsten Heimrich 	if (!fDayNameHeaderVisible)
124178092ae7SKarsten Heimrich 		rows = 6;
124278092ae7SKarsten Heimrich 
124378092ae7SKarsten Heimrich 	if (!fWeekNumberHeaderVisible)
124478092ae7SKarsten Heimrich 		columns = 7;
124578092ae7SKarsten Heimrich 
124678092ae7SKarsten Heimrich 	BRect frame = Bounds();
124778092ae7SKarsten Heimrich 	frame.right = frame.Width() / columns - 1.0;
124878092ae7SKarsten Heimrich 	frame.bottom = frame.Height() / rows - 1.0;
124978092ae7SKarsten Heimrich 
125078092ae7SKarsten Heimrich 	float offsetY = 4.0;
125178092ae7SKarsten Heimrich 	if (fDayNameHeaderVisible)
125278092ae7SKarsten Heimrich 		offsetY += frame.Height();
125378092ae7SKarsten Heimrich 
125478092ae7SKarsten Heimrich 	float offsetX = 4.0;
125578092ae7SKarsten Heimrich 	if (fWeekNumberHeaderVisible)
125678092ae7SKarsten Heimrich 		offsetX += frame.Width();
125778092ae7SKarsten Heimrich 
125878092ae7SKarsten Heimrich 	return frame.OffsetBySelf(offsetX, offsetY);
125978092ae7SKarsten Heimrich }
126078092ae7SKarsten Heimrich 
126178092ae7SKarsten Heimrich 
126278092ae7SKarsten Heimrich BRect
126378092ae7SKarsten Heimrich BCalendarView::_SetNewSelectedDay(const BPoint& where)
126478092ae7SKarsten Heimrich {
126578092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
126678092ae7SKarsten Heimrich 
126778092ae7SKarsten Heimrich 	int32 counter = 0;
126878092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
126978092ae7SKarsten Heimrich 		BRect tmp = frame;
127078092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
127178092ae7SKarsten Heimrich 			counter++;
127278092ae7SKarsten Heimrich 			if (tmp.Contains(where)) {
127378092ae7SKarsten Heimrich 				fNewSelectedDay.SetTo(row, column);
12746846765fSOliver Tappe 				int32 year;
12756846765fSOliver Tappe 				int32 month;
12766846765fSOliver Tappe 				_GetYearMonthForSelection(fNewSelectedDay, &year, &month);
12776846765fSOliver Tappe 				if (month == fDate.Month()) {
12786846765fSOliver Tappe 					// only change date if a day in the current month has been
12796846765fSOliver Tappe 					// selected
12806846765fSOliver Tappe 					int32 day = atoi(fDayNumbers[row][column].String());
12816846765fSOliver Tappe 					fDate.SetDate(year, month, day);
12826846765fSOliver Tappe 				}
128378092ae7SKarsten Heimrich 				return tmp;
128478092ae7SKarsten Heimrich 			}
128578092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
128678092ae7SKarsten Heimrich 		}
128778092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
128878092ae7SKarsten Heimrich 	}
128978092ae7SKarsten Heimrich 
129078092ae7SKarsten Heimrich 	return frame;
129178092ae7SKarsten Heimrich }
129278092ae7SKarsten Heimrich 
129378092ae7SKarsten Heimrich 
129478092ae7SKarsten Heimrich BRect
129578092ae7SKarsten Heimrich BCalendarView::_RectOfDay(const Selection& selection) const
129678092ae7SKarsten Heimrich {
129778092ae7SKarsten Heimrich 	BRect frame = _FirstCalendarItemFrame();
129878092ae7SKarsten Heimrich 
129978092ae7SKarsten Heimrich 	int32 counter = 0;
130078092ae7SKarsten Heimrich 	for (int32 row = 0; row < 6; ++row) {
130178092ae7SKarsten Heimrich 		BRect tmp = frame;
130278092ae7SKarsten Heimrich 		for (int32 column = 0; column < 7; ++column) {
130378092ae7SKarsten Heimrich 			counter++;
13046846765fSOliver Tappe 			if (selection.row == row && selection.column == column)
130578092ae7SKarsten Heimrich 				return tmp;
130678092ae7SKarsten Heimrich 			tmp.OffsetBy(tmp.Width(), 0.0);
130778092ae7SKarsten Heimrich 		}
130878092ae7SKarsten Heimrich 		frame.OffsetBy(0.0, frame.Height());
130978092ae7SKarsten Heimrich 	}
131078092ae7SKarsten Heimrich 
131178092ae7SKarsten Heimrich 	return frame;
131278092ae7SKarsten Heimrich }
131378092ae7SKarsten Heimrich 
131478092ae7SKarsten Heimrich 
131578092ae7SKarsten Heimrich }	// namespace BPrivate
1316