178092ae7SKarsten Heimrich /* 2c8b61804SAxel Dörfler * Copyright 2007-2011, Haiku, Inc. All Rights Reserved. 378092ae7SKarsten Heimrich * Distributed under the terms of the MIT License. 478092ae7SKarsten Heimrich * 578092ae7SKarsten Heimrich * Authors: 678092ae7SKarsten Heimrich * Julun <host.haiku@gmx.de> 778092ae7SKarsten Heimrich */ 878092ae7SKarsten Heimrich 91b3303e7SAxel Dörfler 1078092ae7SKarsten Heimrich #include "CalendarView.h" 1178092ae7SKarsten Heimrich 121b3303e7SAxel Dörfler #include <stdlib.h> 1378092ae7SKarsten Heimrich 142530274dSRyan Leavengood #include <LayoutUtils.h> 1578092ae7SKarsten Heimrich #include <Window.h> 1678092ae7SKarsten Heimrich 1778092ae7SKarsten Heimrich 1878092ae7SKarsten Heimrich namespace BPrivate { 1978092ae7SKarsten Heimrich 201b3303e7SAxel Dörfler 21c8b61804SAxel Dörfler static float 2278092ae7SKarsten Heimrich FontHeight(const BView* view) 2378092ae7SKarsten Heimrich { 2478092ae7SKarsten Heimrich if (!view) 2578092ae7SKarsten Heimrich return 0.0; 2678092ae7SKarsten Heimrich 2778092ae7SKarsten Heimrich BFont font; 2878092ae7SKarsten Heimrich view->GetFont(&font); 2978092ae7SKarsten Heimrich font_height fheight; 3078092ae7SKarsten Heimrich font.GetHeight(&fheight); 3178092ae7SKarsten Heimrich return ceilf(fheight.ascent + fheight.descent + fheight.leading); 3278092ae7SKarsten Heimrich } 331b3303e7SAxel Dörfler 34c8b61804SAxel Dörfler 35c8b61804SAxel Dörfler // #pragma mark - 3678092ae7SKarsten Heimrich 3778092ae7SKarsten Heimrich 386846765fSOliver Tappe BCalendarView::BCalendarView(BRect frame, const char* name, uint32 resizeMask, 396846765fSOliver Tappe uint32 flags) 401b3303e7SAxel Dörfler : 411b3303e7SAxel Dörfler BView(frame, name, resizeMask, flags), 4278092ae7SKarsten Heimrich BInvoker(), 4378092ae7SKarsten Heimrich fSelectionMessage(NULL), 446846765fSOliver Tappe fDate(), 4578092ae7SKarsten Heimrich fFocusChanged(false), 4678092ae7SKarsten Heimrich fSelectionChanged(false), 476846765fSOliver Tappe fStartOfWeek((int32)B_WEEKDAY_MONDAY), 4878092ae7SKarsten Heimrich fDayNameHeaderVisible(true), 4978092ae7SKarsten Heimrich fWeekNumberHeaderVisible(true) 5078092ae7SKarsten Heimrich { 5178092ae7SKarsten Heimrich _InitObject(); 5278092ae7SKarsten Heimrich } 5378092ae7SKarsten Heimrich 5478092ae7SKarsten Heimrich 552530274dSRyan Leavengood BCalendarView::BCalendarView(const char* name, uint32 flags) 562530274dSRyan Leavengood : 572530274dSRyan Leavengood BView(name, flags), 582530274dSRyan Leavengood BInvoker(), 592530274dSRyan Leavengood fSelectionMessage(NULL), 606846765fSOliver Tappe fDate(), 612530274dSRyan Leavengood fFocusChanged(false), 622530274dSRyan Leavengood fSelectionChanged(false), 636846765fSOliver Tappe fStartOfWeek((int32)B_WEEKDAY_MONDAY), 641e07062bSOliver Tappe fDayNameHeaderVisible(true), 651e07062bSOliver Tappe fWeekNumberHeaderVisible(true) 661e07062bSOliver Tappe { 671e07062bSOliver Tappe _InitObject(); 681e07062bSOliver Tappe } 691e07062bSOliver Tappe 701e07062bSOliver Tappe 7178092ae7SKarsten Heimrich BCalendarView::~BCalendarView() 7278092ae7SKarsten Heimrich { 7378092ae7SKarsten Heimrich SetSelectionMessage(NULL); 7478092ae7SKarsten Heimrich } 7578092ae7SKarsten Heimrich 7678092ae7SKarsten Heimrich 7778092ae7SKarsten Heimrich BCalendarView::BCalendarView(BMessage* archive) 781b3303e7SAxel Dörfler : 791b3303e7SAxel Dörfler BView(archive), 8078092ae7SKarsten Heimrich BInvoker(), 8178092ae7SKarsten Heimrich fSelectionMessage(NULL), 826846765fSOliver Tappe fDate(archive), 8378092ae7SKarsten Heimrich fFocusChanged(false), 8478092ae7SKarsten Heimrich fSelectionChanged(false), 856846765fSOliver Tappe fStartOfWeek((int32)B_WEEKDAY_MONDAY), 8678092ae7SKarsten Heimrich fDayNameHeaderVisible(true), 8778092ae7SKarsten Heimrich fWeekNumberHeaderVisible(true) 8878092ae7SKarsten Heimrich { 8978092ae7SKarsten Heimrich if (archive->HasMessage("_invokeMsg")) { 9078092ae7SKarsten Heimrich BMessage* invokationMessage = new BMessage; 9178092ae7SKarsten Heimrich archive->FindMessage("_invokeMsg", invokationMessage); 9278092ae7SKarsten Heimrich SetInvocationMessage(invokationMessage); 9378092ae7SKarsten Heimrich } 9478092ae7SKarsten Heimrich 9578092ae7SKarsten Heimrich if (archive->HasMessage("_selectMsg")) { 9678092ae7SKarsten Heimrich BMessage* selectionMessage = new BMessage; 9778092ae7SKarsten Heimrich archive->FindMessage("selectMsg", selectionMessage); 9878092ae7SKarsten Heimrich SetSelectionMessage(selectionMessage); 9978092ae7SKarsten Heimrich } 10078092ae7SKarsten Heimrich 1016846765fSOliver Tappe if (archive->FindInt32("_weekStart", &fStartOfWeek) != B_OK) 1026846765fSOliver Tappe fStartOfWeek = (int32)B_WEEKDAY_MONDAY; 10378092ae7SKarsten Heimrich 10478092ae7SKarsten Heimrich if (archive->FindBool("_dayHeader", &fDayNameHeaderVisible) != B_OK) 10578092ae7SKarsten Heimrich fDayNameHeaderVisible = true; 10678092ae7SKarsten Heimrich 10778092ae7SKarsten Heimrich if (archive->FindBool("_weekHeader", &fWeekNumberHeaderVisible) != B_OK) 10878092ae7SKarsten Heimrich fWeekNumberHeaderVisible = true; 10978092ae7SKarsten Heimrich 11078092ae7SKarsten Heimrich _SetupDayNames(); 11178092ae7SKarsten Heimrich _SetupDayNumbers(); 11278092ae7SKarsten Heimrich _SetupWeekNumbers(); 11378092ae7SKarsten Heimrich } 11478092ae7SKarsten Heimrich 11578092ae7SKarsten Heimrich 11678092ae7SKarsten Heimrich BArchivable* 11778092ae7SKarsten Heimrich BCalendarView::Instantiate(BMessage* archive) 11878092ae7SKarsten Heimrich { 11978092ae7SKarsten Heimrich if (validate_instantiation(archive, "BCalendarView")) 12078092ae7SKarsten Heimrich return new BCalendarView(archive); 12178092ae7SKarsten Heimrich 12278092ae7SKarsten Heimrich return NULL; 12378092ae7SKarsten Heimrich } 12478092ae7SKarsten Heimrich 12578092ae7SKarsten Heimrich 12678092ae7SKarsten Heimrich status_t 12778092ae7SKarsten Heimrich BCalendarView::Archive(BMessage* archive, bool deep) const 12878092ae7SKarsten Heimrich { 12978092ae7SKarsten Heimrich status_t status = BView::Archive(archive, deep); 13078092ae7SKarsten Heimrich 13178092ae7SKarsten Heimrich if (status == B_OK && InvocationMessage()) 13278092ae7SKarsten Heimrich status = archive->AddMessage("_invokeMsg", InvocationMessage()); 13378092ae7SKarsten Heimrich 13478092ae7SKarsten Heimrich if (status == B_OK && SelectionMessage()) 13578092ae7SKarsten Heimrich status = archive->AddMessage("_selectMsg", SelectionMessage()); 13678092ae7SKarsten Heimrich 13778092ae7SKarsten Heimrich if (status == B_OK) 1386846765fSOliver Tappe status = fDate.Archive(archive); 13978092ae7SKarsten Heimrich 14078092ae7SKarsten Heimrich if (status == B_OK) 1416846765fSOliver Tappe status = archive->AddInt32("_weekStart", fStartOfWeek); 14278092ae7SKarsten Heimrich 14378092ae7SKarsten Heimrich if (status == B_OK) 14478092ae7SKarsten Heimrich status = archive->AddBool("_dayHeader", fDayNameHeaderVisible); 14578092ae7SKarsten Heimrich 14678092ae7SKarsten Heimrich if (status == B_OK) 14778092ae7SKarsten Heimrich status = archive->AddBool("_weekHeader", fWeekNumberHeaderVisible); 14878092ae7SKarsten Heimrich 14978092ae7SKarsten Heimrich return status; 15078092ae7SKarsten Heimrich } 15178092ae7SKarsten Heimrich 15278092ae7SKarsten Heimrich 15378092ae7SKarsten Heimrich void 15478092ae7SKarsten Heimrich BCalendarView::AttachedToWindow() 15578092ae7SKarsten Heimrich { 15678092ae7SKarsten Heimrich BView::AttachedToWindow(); 15778092ae7SKarsten Heimrich 15878092ae7SKarsten Heimrich if (!Messenger().IsValid()) 15978092ae7SKarsten Heimrich SetTarget(Window(), NULL); 160*99e015b4SJanus 161*99e015b4SJanus SetViewColor(ui_color(B_LIST_BACKGROUND_COLOR)); 16278092ae7SKarsten Heimrich } 16378092ae7SKarsten Heimrich 16478092ae7SKarsten Heimrich 16578092ae7SKarsten Heimrich void 16678092ae7SKarsten Heimrich BCalendarView::FrameResized(float width, float height) 16778092ae7SKarsten Heimrich { 16878092ae7SKarsten Heimrich Invalidate(Bounds()); 16978092ae7SKarsten Heimrich } 17078092ae7SKarsten Heimrich 17178092ae7SKarsten Heimrich 17278092ae7SKarsten Heimrich void 17378092ae7SKarsten Heimrich BCalendarView::Draw(BRect updateRect) 17478092ae7SKarsten Heimrich { 17578092ae7SKarsten Heimrich if (LockLooper()) { 17678092ae7SKarsten Heimrich if (fFocusChanged) { 17778092ae7SKarsten Heimrich _DrawFocusRect(); 17878092ae7SKarsten Heimrich UnlockLooper(); 17978092ae7SKarsten Heimrich return; 18078092ae7SKarsten Heimrich } 18178092ae7SKarsten Heimrich 18278092ae7SKarsten Heimrich if (fSelectionChanged) { 18378092ae7SKarsten Heimrich _UpdateSelection(); 18478092ae7SKarsten Heimrich UnlockLooper(); 18578092ae7SKarsten Heimrich return; 18678092ae7SKarsten Heimrich } 18778092ae7SKarsten Heimrich 18878092ae7SKarsten Heimrich _DrawDays(); 18978092ae7SKarsten Heimrich _DrawDayHeader(); 19078092ae7SKarsten Heimrich _DrawWeekHeader(); 19178092ae7SKarsten Heimrich 19278092ae7SKarsten Heimrich rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); 19378092ae7SKarsten Heimrich SetHighColor(tint_color(background, B_DARKEN_3_TINT)); 19478092ae7SKarsten Heimrich StrokeRect(Bounds()); 19578092ae7SKarsten Heimrich 19678092ae7SKarsten Heimrich UnlockLooper(); 19778092ae7SKarsten Heimrich } 19878092ae7SKarsten Heimrich } 19978092ae7SKarsten Heimrich 20078092ae7SKarsten Heimrich 20178092ae7SKarsten Heimrich void 20278092ae7SKarsten Heimrich BCalendarView::DrawDay(BView* owner, BRect frame, const char* text, 20378092ae7SKarsten Heimrich bool isSelected, bool isEnabled, bool focus) 20478092ae7SKarsten Heimrich { 20578092ae7SKarsten Heimrich _DrawItem(owner, frame, text, isSelected, isEnabled, focus); 20678092ae7SKarsten Heimrich } 20778092ae7SKarsten Heimrich 20878092ae7SKarsten Heimrich 20978092ae7SKarsten Heimrich void 21078092ae7SKarsten Heimrich BCalendarView::DrawDayName(BView* owner, BRect frame, const char* text) 21178092ae7SKarsten Heimrich { 21278092ae7SKarsten Heimrich // we get the full rect, fake this as the internal function 21378092ae7SKarsten Heimrich // shrinks the frame to work properly when drawing a day item 21478092ae7SKarsten Heimrich _DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true); 21578092ae7SKarsten Heimrich } 21678092ae7SKarsten Heimrich 21778092ae7SKarsten Heimrich 21878092ae7SKarsten Heimrich void 21978092ae7SKarsten Heimrich BCalendarView::DrawWeekNumber(BView* owner, BRect frame, const char* text) 22078092ae7SKarsten Heimrich { 22178092ae7SKarsten Heimrich // we get the full rect, fake this as the internal function 22278092ae7SKarsten Heimrich // shrinks the frame to work properly when drawing a day item 22378092ae7SKarsten Heimrich _DrawItem(owner, frame.InsetByCopy(-1.0, -1.0), text, true); 22478092ae7SKarsten Heimrich } 22578092ae7SKarsten Heimrich 22678092ae7SKarsten Heimrich 22778092ae7SKarsten Heimrich uint32 22878092ae7SKarsten Heimrich BCalendarView::SelectionCommand() const 22978092ae7SKarsten Heimrich { 23078092ae7SKarsten Heimrich if (SelectionMessage()) 23178092ae7SKarsten Heimrich return SelectionMessage()->what; 23278092ae7SKarsten Heimrich 23378092ae7SKarsten Heimrich return 0; 23478092ae7SKarsten Heimrich } 23578092ae7SKarsten Heimrich 23678092ae7SKarsten Heimrich 23778092ae7SKarsten Heimrich BMessage* 23878092ae7SKarsten Heimrich BCalendarView::SelectionMessage() const 23978092ae7SKarsten Heimrich { 24078092ae7SKarsten Heimrich return fSelectionMessage; 24178092ae7SKarsten Heimrich } 24278092ae7SKarsten Heimrich 24378092ae7SKarsten Heimrich 24478092ae7SKarsten Heimrich void 24578092ae7SKarsten Heimrich BCalendarView::SetSelectionMessage(BMessage* message) 24678092ae7SKarsten Heimrich { 24778092ae7SKarsten Heimrich delete fSelectionMessage; 24878092ae7SKarsten Heimrich fSelectionMessage = message; 24978092ae7SKarsten Heimrich } 25078092ae7SKarsten Heimrich 25178092ae7SKarsten Heimrich 25278092ae7SKarsten Heimrich uint32 25378092ae7SKarsten Heimrich BCalendarView::InvocationCommand() const 25478092ae7SKarsten Heimrich { 25578092ae7SKarsten Heimrich return BInvoker::Command(); 25678092ae7SKarsten Heimrich } 25778092ae7SKarsten Heimrich 25878092ae7SKarsten Heimrich 25978092ae7SKarsten Heimrich BMessage* 26078092ae7SKarsten Heimrich BCalendarView::InvocationMessage() const 26178092ae7SKarsten Heimrich { 26278092ae7SKarsten Heimrich return BInvoker::Message(); 26378092ae7SKarsten Heimrich } 26478092ae7SKarsten Heimrich 26578092ae7SKarsten Heimrich 26678092ae7SKarsten Heimrich void 26778092ae7SKarsten Heimrich BCalendarView::SetInvocationMessage(BMessage* message) 26878092ae7SKarsten Heimrich { 26978092ae7SKarsten Heimrich BInvoker::SetMessage(message); 27078092ae7SKarsten Heimrich } 27178092ae7SKarsten Heimrich 27278092ae7SKarsten Heimrich 27378092ae7SKarsten Heimrich void 27478092ae7SKarsten Heimrich BCalendarView::MakeFocus(bool state) 27578092ae7SKarsten Heimrich { 27678092ae7SKarsten Heimrich if (IsFocus() == state) 27778092ae7SKarsten Heimrich return; 27878092ae7SKarsten Heimrich 27978092ae7SKarsten Heimrich BView::MakeFocus(state); 28078092ae7SKarsten Heimrich 2811b3303e7SAxel Dörfler // TODO: solve this better 28278092ae7SKarsten Heimrich fFocusChanged = true; 28378092ae7SKarsten Heimrich Draw(_RectOfDay(fFocusedDay)); 28478092ae7SKarsten Heimrich fFocusChanged = false; 28578092ae7SKarsten Heimrich } 28678092ae7SKarsten Heimrich 28778092ae7SKarsten Heimrich 28878092ae7SKarsten Heimrich status_t 28978092ae7SKarsten Heimrich BCalendarView::Invoke(BMessage* message) 29078092ae7SKarsten Heimrich { 29178092ae7SKarsten Heimrich bool notify = false; 29278092ae7SKarsten Heimrich uint32 kind = InvokeKind(¬ify); 29378092ae7SKarsten Heimrich 29478092ae7SKarsten Heimrich BMessage clone(kind); 29578092ae7SKarsten Heimrich status_t status = B_BAD_VALUE; 29678092ae7SKarsten Heimrich 29778092ae7SKarsten Heimrich if (!message && !notify) 29878092ae7SKarsten Heimrich message = Message(); 29978092ae7SKarsten Heimrich 30078092ae7SKarsten Heimrich if (!message) { 30178092ae7SKarsten Heimrich if (!IsWatched()) 30278092ae7SKarsten Heimrich return status; 30378092ae7SKarsten Heimrich } else 30478092ae7SKarsten Heimrich clone = *message; 30578092ae7SKarsten Heimrich 30678092ae7SKarsten Heimrich clone.AddPointer("source", this); 30778092ae7SKarsten Heimrich clone.AddInt64("when", (int64)system_time()); 30878092ae7SKarsten Heimrich clone.AddMessenger("be:sender", BMessenger(this)); 30978092ae7SKarsten Heimrich 31078092ae7SKarsten Heimrich int32 year; 31178092ae7SKarsten Heimrich int32 month; 3126846765fSOliver Tappe _GetYearMonthForSelection(fSelectedDay, &year, &month); 31378092ae7SKarsten Heimrich 3146846765fSOliver Tappe clone.AddInt32("year", fDate.Year()); 3156846765fSOliver Tappe clone.AddInt32("month", fDate.Month()); 3166846765fSOliver Tappe clone.AddInt32("day", fDate.Day()); 31778092ae7SKarsten Heimrich 31878092ae7SKarsten Heimrich if (message) 31978092ae7SKarsten Heimrich status = BInvoker::Invoke(&clone); 32078092ae7SKarsten Heimrich 32178092ae7SKarsten Heimrich SendNotices(kind, &clone); 32278092ae7SKarsten Heimrich 32378092ae7SKarsten Heimrich return status; 32478092ae7SKarsten Heimrich } 32578092ae7SKarsten Heimrich 32678092ae7SKarsten Heimrich 32778092ae7SKarsten Heimrich void 32878092ae7SKarsten Heimrich BCalendarView::MouseDown(BPoint where) 32978092ae7SKarsten Heimrich { 33078092ae7SKarsten Heimrich if (!IsFocus()) { 33178092ae7SKarsten Heimrich MakeFocus(); 33278092ae7SKarsten Heimrich Sync(); 33378092ae7SKarsten Heimrich Window()->UpdateIfNeeded(); 33478092ae7SKarsten Heimrich } 33578092ae7SKarsten Heimrich 33678092ae7SKarsten Heimrich BRect frame = Bounds(); 33778092ae7SKarsten Heimrich if (fDayNameHeaderVisible) 33878092ae7SKarsten Heimrich frame.top += frame.Height() / 7 - 1.0; 33978092ae7SKarsten Heimrich 34078092ae7SKarsten Heimrich if (fWeekNumberHeaderVisible) 34178092ae7SKarsten Heimrich frame.left += frame.Width() / 8 - 1.0; 34278092ae7SKarsten Heimrich 34378092ae7SKarsten Heimrich if (!frame.Contains(where)) 34478092ae7SKarsten Heimrich return; 34578092ae7SKarsten Heimrich 34678092ae7SKarsten Heimrich // try to set to new day 34778092ae7SKarsten Heimrich frame = _SetNewSelectedDay(where); 34878092ae7SKarsten Heimrich 34978092ae7SKarsten Heimrich // on success 35078092ae7SKarsten Heimrich if (fSelectedDay != fNewSelectedDay) { 35178092ae7SKarsten Heimrich // update focus 35278092ae7SKarsten Heimrich fFocusChanged = true; 35378092ae7SKarsten Heimrich fNewFocusedDay = fNewSelectedDay; 35478092ae7SKarsten Heimrich Draw(_RectOfDay(fFocusedDay)); 35578092ae7SKarsten Heimrich fFocusChanged = false; 35678092ae7SKarsten Heimrich 35778092ae7SKarsten Heimrich // update selection 35878092ae7SKarsten Heimrich fSelectionChanged = true; 35978092ae7SKarsten Heimrich Draw(frame); 36078092ae7SKarsten Heimrich Draw(_RectOfDay(fSelectedDay)); 36178092ae7SKarsten Heimrich fSelectionChanged = false; 36278092ae7SKarsten Heimrich 36378092ae7SKarsten Heimrich // notify that selection changed 36478092ae7SKarsten Heimrich InvokeNotify(SelectionMessage(), B_CONTROL_MODIFIED); 36578092ae7SKarsten Heimrich } 36678092ae7SKarsten Heimrich 36778092ae7SKarsten Heimrich int32 clicks; 36878092ae7SKarsten Heimrich // on double click invoke 36978092ae7SKarsten Heimrich BMessage* message = Looper()->CurrentMessage(); 37078092ae7SKarsten Heimrich if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1) 37178092ae7SKarsten Heimrich Invoke(); 37278092ae7SKarsten Heimrich } 37378092ae7SKarsten Heimrich 37478092ae7SKarsten Heimrich 37578092ae7SKarsten Heimrich void 37678092ae7SKarsten Heimrich BCalendarView::KeyDown(const char* bytes, int32 numBytes) 37778092ae7SKarsten Heimrich { 37878092ae7SKarsten Heimrich const int32 kRows = 6; 37978092ae7SKarsten Heimrich const int32 kColumns = 7; 38078092ae7SKarsten Heimrich 38178092ae7SKarsten Heimrich int32 row = fFocusedDay.row; 38278092ae7SKarsten Heimrich int32 column = fFocusedDay.column; 38378092ae7SKarsten Heimrich 38478092ae7SKarsten Heimrich switch (bytes[0]) { 38578092ae7SKarsten Heimrich case B_LEFT_ARROW: 38678092ae7SKarsten Heimrich column -= 1; 38778092ae7SKarsten Heimrich if (column < 0) { 38878092ae7SKarsten Heimrich column = kColumns - 1; 38978092ae7SKarsten Heimrich row -= 1; 39078092ae7SKarsten Heimrich if (row >= 0) 39178092ae7SKarsten Heimrich fFocusChanged = true; 39278092ae7SKarsten Heimrich } else 39378092ae7SKarsten Heimrich fFocusChanged = true; 3946846765fSOliver Tappe break; 39578092ae7SKarsten Heimrich 39678092ae7SKarsten Heimrich case B_RIGHT_ARROW: 39778092ae7SKarsten Heimrich column += 1; 39878092ae7SKarsten Heimrich if (column == kColumns) { 39978092ae7SKarsten Heimrich column = 0; 40078092ae7SKarsten Heimrich row += 1; 40178092ae7SKarsten Heimrich if (row < kRows) 40278092ae7SKarsten Heimrich fFocusChanged = true; 40378092ae7SKarsten Heimrich } else 40478092ae7SKarsten Heimrich fFocusChanged = true; 4056846765fSOliver Tappe break; 40678092ae7SKarsten Heimrich 40778092ae7SKarsten Heimrich case B_UP_ARROW: 40878092ae7SKarsten Heimrich row -= 1; 40978092ae7SKarsten Heimrich if (row >= 0) 41078092ae7SKarsten Heimrich fFocusChanged = true; 4116846765fSOliver Tappe break; 41278092ae7SKarsten Heimrich 41378092ae7SKarsten Heimrich case B_DOWN_ARROW: 41478092ae7SKarsten Heimrich row += 1; 41578092ae7SKarsten Heimrich if (row < kRows) 41678092ae7SKarsten Heimrich fFocusChanged = true; 4176846765fSOliver Tappe break; 4186846765fSOliver Tappe 4196846765fSOliver Tappe case B_PAGE_UP: 4206846765fSOliver Tappe { 4216846765fSOliver Tappe BDate date(fDate); 4226846765fSOliver Tappe date.AddMonths(-1); 4236846765fSOliver Tappe SetDate(date); 4246846765fSOliver Tappe 4256846765fSOliver Tappe Invoke(); 4266846765fSOliver Tappe break; 4276846765fSOliver Tappe } 4286846765fSOliver Tappe 4296846765fSOliver Tappe case B_PAGE_DOWN: 4306846765fSOliver Tappe { 4316846765fSOliver Tappe BDate date(fDate); 4326846765fSOliver Tappe date.AddMonths(1); 4336846765fSOliver Tappe SetDate(date); 4346846765fSOliver Tappe 4356846765fSOliver Tappe Invoke(); 4366846765fSOliver Tappe break; 4376846765fSOliver Tappe } 43878092ae7SKarsten Heimrich 43978092ae7SKarsten Heimrich case B_RETURN: 4406846765fSOliver Tappe case B_SPACE: 4416846765fSOliver Tappe { 44278092ae7SKarsten Heimrich fSelectionChanged = true; 44378092ae7SKarsten Heimrich BPoint pt = _RectOfDay(fFocusedDay).LeftTop(); 44478092ae7SKarsten Heimrich Draw(_SetNewSelectedDay(pt + BPoint(4.0, 4.0))); 44578092ae7SKarsten Heimrich Draw(_RectOfDay(fSelectedDay)); 44678092ae7SKarsten Heimrich fSelectionChanged = false; 44778092ae7SKarsten Heimrich 44878092ae7SKarsten Heimrich Invoke(); 4496846765fSOliver Tappe break; 4506846765fSOliver Tappe } 45178092ae7SKarsten Heimrich 45278092ae7SKarsten Heimrich default: 45378092ae7SKarsten Heimrich BView::KeyDown(bytes, numBytes); 45478092ae7SKarsten Heimrich break; 45578092ae7SKarsten Heimrich } 45678092ae7SKarsten Heimrich 45778092ae7SKarsten Heimrich if (fFocusChanged) { 45878092ae7SKarsten Heimrich fNewFocusedDay.SetTo(row, column); 45978092ae7SKarsten Heimrich Draw(_RectOfDay(fFocusedDay)); 46078092ae7SKarsten Heimrich Draw(_RectOfDay(fNewFocusedDay)); 46178092ae7SKarsten Heimrich fFocusChanged = false; 46278092ae7SKarsten Heimrich } 46378092ae7SKarsten Heimrich } 46478092ae7SKarsten Heimrich 46578092ae7SKarsten Heimrich 46678092ae7SKarsten Heimrich void 46778092ae7SKarsten Heimrich BCalendarView::ResizeToPreferred() 46878092ae7SKarsten Heimrich { 46978092ae7SKarsten Heimrich float width; 47078092ae7SKarsten Heimrich float height; 47178092ae7SKarsten Heimrich 47278092ae7SKarsten Heimrich GetPreferredSize(&width, &height); 47378092ae7SKarsten Heimrich BView::ResizeTo(width, height); 47478092ae7SKarsten Heimrich } 47578092ae7SKarsten Heimrich 47678092ae7SKarsten Heimrich 47778092ae7SKarsten Heimrich void 47878092ae7SKarsten Heimrich BCalendarView::GetPreferredSize(float* width, float* height) 47978092ae7SKarsten Heimrich { 48078092ae7SKarsten Heimrich _GetPreferredSize(width, height); 48178092ae7SKarsten Heimrich } 48278092ae7SKarsten Heimrich 48378092ae7SKarsten Heimrich 4842530274dSRyan Leavengood BSize 4852530274dSRyan Leavengood BCalendarView::MaxSize() 4862530274dSRyan Leavengood { 4872530274dSRyan Leavengood return BLayoutUtils::ComposeSize(ExplicitMaxSize(), 4882530274dSRyan Leavengood BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); 4892530274dSRyan Leavengood } 4902530274dSRyan Leavengood 4912530274dSRyan Leavengood 4922530274dSRyan Leavengood BSize 4932530274dSRyan Leavengood BCalendarView::MinSize() 4942530274dSRyan Leavengood { 4952530274dSRyan Leavengood float width, height; 4962530274dSRyan Leavengood _GetPreferredSize(&width, &height); 4976846765fSOliver Tappe return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(width, height)); 4982530274dSRyan Leavengood } 4992530274dSRyan Leavengood 5002530274dSRyan Leavengood 5012530274dSRyan Leavengood BSize 5022530274dSRyan Leavengood BCalendarView::PreferredSize() 5032530274dSRyan Leavengood { 5046846765fSOliver Tappe return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize()); 5052530274dSRyan Leavengood } 5062530274dSRyan Leavengood 5072530274dSRyan Leavengood 50878092ae7SKarsten Heimrich int32 50978092ae7SKarsten Heimrich BCalendarView::Day() const 51078092ae7SKarsten Heimrich { 5116846765fSOliver Tappe return fDate.Day(); 51278092ae7SKarsten Heimrich } 51378092ae7SKarsten Heimrich 51478092ae7SKarsten Heimrich 51578092ae7SKarsten Heimrich int32 51678092ae7SKarsten Heimrich BCalendarView::Year() const 51778092ae7SKarsten Heimrich { 51878092ae7SKarsten Heimrich int32 year; 5196846765fSOliver Tappe _GetYearMonthForSelection(fSelectedDay, &year, NULL); 52078092ae7SKarsten Heimrich 52178092ae7SKarsten Heimrich return year; 52278092ae7SKarsten Heimrich } 52378092ae7SKarsten Heimrich 52478092ae7SKarsten Heimrich 52578092ae7SKarsten Heimrich int32 52678092ae7SKarsten Heimrich BCalendarView::Month() const 52778092ae7SKarsten Heimrich { 52878092ae7SKarsten Heimrich int32 month; 5296846765fSOliver Tappe _GetYearMonthForSelection(fSelectedDay, NULL, &month); 53078092ae7SKarsten Heimrich 53178092ae7SKarsten Heimrich return month; 53278092ae7SKarsten Heimrich } 53378092ae7SKarsten Heimrich 53478092ae7SKarsten Heimrich 535afd5ec11SAdrien Destugues bool 536afd5ec11SAdrien Destugues BCalendarView::SetDay(int32 day) 537afd5ec11SAdrien Destugues { 538afd5ec11SAdrien Destugues BDate date = Date(); 539afd5ec11SAdrien Destugues date.SetDay(day); 540afd5ec11SAdrien Destugues if (!date.IsValid()) 541afd5ec11SAdrien Destugues return false; 542afd5ec11SAdrien Destugues SetDate(date); 543afd5ec11SAdrien Destugues return true; 544afd5ec11SAdrien Destugues } 545afd5ec11SAdrien Destugues 546afd5ec11SAdrien Destugues 547afd5ec11SAdrien Destugues bool 548afd5ec11SAdrien Destugues BCalendarView::SetMonth(int32 month) 549afd5ec11SAdrien Destugues { 550afd5ec11SAdrien Destugues if (month < 1 || month > 12) 551afd5ec11SAdrien Destugues return false; 552afd5ec11SAdrien Destugues BDate date = Date(); 553afd5ec11SAdrien Destugues int32 oldDay = date.Day(); 554afd5ec11SAdrien Destugues 555afd5ec11SAdrien Destugues date.SetMonth(month); 556afd5ec11SAdrien Destugues date.SetDay(1); // make sure the date is valid 557afd5ec11SAdrien Destugues 558afd5ec11SAdrien Destugues // We must make sure that the day in month fits inside the new month. 559afd5ec11SAdrien Destugues if (oldDay > date.DaysInMonth()) 560afd5ec11SAdrien Destugues date.SetDay(date.DaysInMonth()); 561afd5ec11SAdrien Destugues else 562afd5ec11SAdrien Destugues date.SetDay(oldDay); 563afd5ec11SAdrien Destugues SetDate(date); 564afd5ec11SAdrien Destugues return true; 565afd5ec11SAdrien Destugues } 566afd5ec11SAdrien Destugues 567afd5ec11SAdrien Destugues 568afd5ec11SAdrien Destugues bool 569afd5ec11SAdrien Destugues BCalendarView::SetYear(int32 year) 570afd5ec11SAdrien Destugues { 571afd5ec11SAdrien Destugues BDate date = Date(); 572afd5ec11SAdrien Destugues 573afd5ec11SAdrien Destugues // This can fail when going from 29 feb. on a leap year to a non-leap year. 574afd5ec11SAdrien Destugues if (date.Month() == 2 && date.Day() == 29 && !date.IsLeapYear(year)) 575afd5ec11SAdrien Destugues date.SetDay(28); 576afd5ec11SAdrien Destugues 577afd5ec11SAdrien Destugues // TODO we should also handle the "hole" at the switch between Julian and 578afd5ec11SAdrien Destugues // Gregorian calendars, which will result in an invalid date. 579afd5ec11SAdrien Destugues 580afd5ec11SAdrien Destugues date.SetYear(year); 581afd5ec11SAdrien Destugues SetDate(date); 582afd5ec11SAdrien Destugues return true; 583afd5ec11SAdrien Destugues } 584afd5ec11SAdrien Destugues 585afd5ec11SAdrien Destugues 58678092ae7SKarsten Heimrich BDate 58778092ae7SKarsten Heimrich BCalendarView::Date() const 58878092ae7SKarsten Heimrich { 58978092ae7SKarsten Heimrich int32 year; 59078092ae7SKarsten Heimrich int32 month; 5916846765fSOliver Tappe _GetYearMonthForSelection(fSelectedDay, &year, &month); 5926846765fSOliver Tappe return BDate(year, month, fDate.Day()); 59378092ae7SKarsten Heimrich } 59478092ae7SKarsten Heimrich 59578092ae7SKarsten Heimrich 59678092ae7SKarsten Heimrich bool 59778092ae7SKarsten Heimrich BCalendarView::SetDate(const BDate& date) 59878092ae7SKarsten Heimrich { 599c1ed5d75SKarsten Heimrich if (!date.IsValid()) 600c1ed5d75SKarsten Heimrich return false; 601c1ed5d75SKarsten Heimrich 6026846765fSOliver Tappe if (fDate == date) 60378092ae7SKarsten Heimrich return true; 60478092ae7SKarsten Heimrich 6056846765fSOliver Tappe if (fDate.Year() == date.Year() && fDate.Month() == date.Month()) { 6066846765fSOliver Tappe fDate = date; 6076846765fSOliver Tappe 60878092ae7SKarsten Heimrich _SetToDay(); 60978092ae7SKarsten Heimrich // update focus 61078092ae7SKarsten Heimrich fFocusChanged = true; 61178092ae7SKarsten Heimrich Draw(_RectOfDay(fFocusedDay)); 61278092ae7SKarsten Heimrich fFocusChanged = false; 61378092ae7SKarsten Heimrich 61478092ae7SKarsten Heimrich // update selection 61578092ae7SKarsten Heimrich fSelectionChanged = true; 61678092ae7SKarsten Heimrich Draw(_RectOfDay(fSelectedDay)); 61778092ae7SKarsten Heimrich Draw(_RectOfDay(fNewSelectedDay)); 61878092ae7SKarsten Heimrich fSelectionChanged = false; 61978092ae7SKarsten Heimrich } else { 6206846765fSOliver Tappe fDate = date; 62178092ae7SKarsten Heimrich 62278092ae7SKarsten Heimrich _SetupDayNumbers(); 62378092ae7SKarsten Heimrich _SetupWeekNumbers(); 62478092ae7SKarsten Heimrich 62578092ae7SKarsten Heimrich BRect frame = Bounds(); 62678092ae7SKarsten Heimrich if (fDayNameHeaderVisible) 62778092ae7SKarsten Heimrich frame.top += frame.Height() / 7 - 1.0; 62878092ae7SKarsten Heimrich 62978092ae7SKarsten Heimrich if (fWeekNumberHeaderVisible) 63078092ae7SKarsten Heimrich frame.left += frame.Width() / 8 - 1.0; 63178092ae7SKarsten Heimrich 63278092ae7SKarsten Heimrich Draw(frame.InsetBySelf(4.0, 4.0)); 63378092ae7SKarsten Heimrich } 63478092ae7SKarsten Heimrich 63578092ae7SKarsten Heimrich return true; 63678092ae7SKarsten Heimrich } 63778092ae7SKarsten Heimrich 63878092ae7SKarsten Heimrich 6396846765fSOliver Tappe bool 6406846765fSOliver Tappe BCalendarView::SetDate(int32 year, int32 month, int32 day) 64178092ae7SKarsten Heimrich { 6426846765fSOliver Tappe return SetDate(BDate(year, month, day)); 6436846765fSOliver Tappe } 6446846765fSOliver Tappe 6456846765fSOliver Tappe 6466846765fSOliver Tappe BWeekday 6476846765fSOliver Tappe BCalendarView::StartOfWeek() const 6486846765fSOliver Tappe { 6496846765fSOliver Tappe return BWeekday(fStartOfWeek); 65078092ae7SKarsten Heimrich } 65178092ae7SKarsten Heimrich 65278092ae7SKarsten Heimrich 65378092ae7SKarsten Heimrich void 6546846765fSOliver Tappe BCalendarView::SetStartOfWeek(BWeekday startOfWeek) 65578092ae7SKarsten Heimrich { 6566846765fSOliver Tappe if (fStartOfWeek == (int32)startOfWeek) 65778092ae7SKarsten Heimrich return; 65878092ae7SKarsten Heimrich 6596846765fSOliver Tappe fStartOfWeek = (int32)startOfWeek; 66078092ae7SKarsten Heimrich 66178092ae7SKarsten Heimrich _SetupDayNames(); 66278092ae7SKarsten Heimrich _SetupDayNumbers(); 66378092ae7SKarsten Heimrich _SetupWeekNumbers(); 66478092ae7SKarsten Heimrich 66578092ae7SKarsten Heimrich Invalidate(Bounds().InsetBySelf(1.0, 1.0)); 66678092ae7SKarsten Heimrich } 66778092ae7SKarsten Heimrich 66878092ae7SKarsten Heimrich 66978092ae7SKarsten Heimrich bool 67078092ae7SKarsten Heimrich BCalendarView::IsDayNameHeaderVisible() const 67178092ae7SKarsten Heimrich { 67278092ae7SKarsten Heimrich return fDayNameHeaderVisible; 67378092ae7SKarsten Heimrich } 67478092ae7SKarsten Heimrich 67578092ae7SKarsten Heimrich 67678092ae7SKarsten Heimrich void 67778092ae7SKarsten Heimrich BCalendarView::SetDayNameHeaderVisible(bool visible) 67878092ae7SKarsten Heimrich { 67978092ae7SKarsten Heimrich if (fDayNameHeaderVisible == visible) 68078092ae7SKarsten Heimrich return; 68178092ae7SKarsten Heimrich 68278092ae7SKarsten Heimrich fDayNameHeaderVisible = visible; 68378092ae7SKarsten Heimrich Invalidate(Bounds().InsetBySelf(1.0, 1.0)); 68478092ae7SKarsten Heimrich } 68578092ae7SKarsten Heimrich 68678092ae7SKarsten Heimrich 68778092ae7SKarsten Heimrich bool 68878092ae7SKarsten Heimrich BCalendarView::IsWeekNumberHeaderVisible() const 68978092ae7SKarsten Heimrich { 69078092ae7SKarsten Heimrich return fWeekNumberHeaderVisible; 69178092ae7SKarsten Heimrich } 69278092ae7SKarsten Heimrich 69378092ae7SKarsten Heimrich 69478092ae7SKarsten Heimrich void 69578092ae7SKarsten Heimrich BCalendarView::SetWeekNumberHeaderVisible(bool visible) 69678092ae7SKarsten Heimrich { 69778092ae7SKarsten Heimrich if (fWeekNumberHeaderVisible == visible) 69878092ae7SKarsten Heimrich return; 69978092ae7SKarsten Heimrich 70078092ae7SKarsten Heimrich fWeekNumberHeaderVisible = visible; 70178092ae7SKarsten Heimrich Invalidate(Bounds().InsetBySelf(1.0, 1.0)); 70278092ae7SKarsten Heimrich } 70378092ae7SKarsten Heimrich 70478092ae7SKarsten Heimrich 70578092ae7SKarsten Heimrich void 70678092ae7SKarsten Heimrich BCalendarView::_InitObject() 70778092ae7SKarsten Heimrich { 7086846765fSOliver Tappe fDate = BDate::CurrentDate(B_LOCAL_TIME); 7096846765fSOliver Tappe 7100a925409SAdrien Destugues BDateFormat().GetStartOfWeek((BWeekday*)&fStartOfWeek); 71178092ae7SKarsten Heimrich 71278092ae7SKarsten Heimrich _SetupDayNames(); 71378092ae7SKarsten Heimrich _SetupDayNumbers(); 71478092ae7SKarsten Heimrich _SetupWeekNumbers(); 71578092ae7SKarsten Heimrich } 71678092ae7SKarsten Heimrich 71778092ae7SKarsten Heimrich 71878092ae7SKarsten Heimrich void 71978092ae7SKarsten Heimrich BCalendarView::_SetToDay() 72078092ae7SKarsten Heimrich { 7216846765fSOliver Tappe BDate date(fDate.Year(), fDate.Month(), 1); 72278092ae7SKarsten Heimrich if (!date.IsValid()) 72378092ae7SKarsten Heimrich return; 72478092ae7SKarsten Heimrich 7256846765fSOliver Tappe const int32 firstDayOffset = (7 + date.DayOfWeek() - fStartOfWeek) % 7; 72678092ae7SKarsten Heimrich 7276846765fSOliver Tappe int32 day = 1 - firstDayOffset; 72878092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 72978092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 7306846765fSOliver Tappe if (day == fDate.Day()) { 73178092ae7SKarsten Heimrich fNewFocusedDay.SetTo(row, column); 73278092ae7SKarsten Heimrich fNewSelectedDay.SetTo(row, column); 73378092ae7SKarsten Heimrich return; 73478092ae7SKarsten Heimrich } 7356846765fSOliver Tappe day++; 73678092ae7SKarsten Heimrich } 73778092ae7SKarsten Heimrich } 7386846765fSOliver Tappe 7396846765fSOliver Tappe fNewFocusedDay.SetTo(0, 0); 7406846765fSOliver Tappe fNewSelectedDay.SetTo(0, 0); 74178092ae7SKarsten Heimrich } 74278092ae7SKarsten Heimrich 74378092ae7SKarsten Heimrich 74478092ae7SKarsten Heimrich void 7456846765fSOliver Tappe BCalendarView::_GetYearMonthForSelection(const Selection& selection, 7466846765fSOliver Tappe int32* year, int32* month) const 74778092ae7SKarsten Heimrich { 7486846765fSOliver Tappe BDate startOfMonth(fDate.Year(), fDate.Month(), 1); 7496846765fSOliver Tappe const int32 firstDayOffset 7506846765fSOliver Tappe = (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7; 7516846765fSOliver Tappe const int32 daysInMonth = startOfMonth.DaysInMonth(); 75278092ae7SKarsten Heimrich 7536846765fSOliver Tappe BDate date(fDate); 7546846765fSOliver Tappe const int32 dayOffset = selection.row * 7 + selection.column; 7556846765fSOliver Tappe if (dayOffset < firstDayOffset) 7566846765fSOliver Tappe date.AddMonths(-1); 7576846765fSOliver Tappe else if (dayOffset >= firstDayOffset + daysInMonth) 7586846765fSOliver Tappe date.AddMonths(1); 7596846765fSOliver Tappe if (year != NULL) 76078092ae7SKarsten Heimrich *year = date.Year(); 7616846765fSOliver Tappe if (month != NULL) 76278092ae7SKarsten Heimrich *month = date.Month(); 76378092ae7SKarsten Heimrich } 76478092ae7SKarsten Heimrich 76578092ae7SKarsten Heimrich 76678092ae7SKarsten Heimrich void 76778092ae7SKarsten Heimrich BCalendarView::_GetPreferredSize(float* _width, float* _height) 76878092ae7SKarsten Heimrich { 76978092ae7SKarsten Heimrich BFont font; 77078092ae7SKarsten Heimrich GetFont(&font); 77178092ae7SKarsten Heimrich font_height fontHeight; 77278092ae7SKarsten Heimrich font.GetHeight(&fontHeight); 77378092ae7SKarsten Heimrich 77478092ae7SKarsten Heimrich const float height = FontHeight(this) + 4.0; 77578092ae7SKarsten Heimrich 77678092ae7SKarsten Heimrich int32 rows = 7; 77778092ae7SKarsten Heimrich if (!fDayNameHeaderVisible) 77878092ae7SKarsten Heimrich rows = 6; 77978092ae7SKarsten Heimrich 78078092ae7SKarsten Heimrich // height = font height * rows + 8 px border 78178092ae7SKarsten Heimrich *_height = height * rows + 8.0; 78278092ae7SKarsten Heimrich 78378092ae7SKarsten Heimrich float width = 0.0; 78478092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 78578092ae7SKarsten Heimrich float tmp = StringWidth(fDayNames[column].String()) + 2.0; 78678092ae7SKarsten Heimrich width = tmp > width ? tmp : width; 78778092ae7SKarsten Heimrich } 78878092ae7SKarsten Heimrich 78978092ae7SKarsten Heimrich int32 columns = 8; 79078092ae7SKarsten Heimrich if (!fWeekNumberHeaderVisible) 79178092ae7SKarsten Heimrich columns = 7; 79278092ae7SKarsten Heimrich 79378092ae7SKarsten Heimrich // width = max width day name * 8 column + 8 px border 79478092ae7SKarsten Heimrich *_width = width * columns + 8.0; 79578092ae7SKarsten Heimrich } 79678092ae7SKarsten Heimrich 79778092ae7SKarsten Heimrich 79878092ae7SKarsten Heimrich void 79978092ae7SKarsten Heimrich BCalendarView::_SetupDayNames() 80078092ae7SKarsten Heimrich { 8016846765fSOliver Tappe for (int32 i = 0; i <= 6; ++i) 8026846765fSOliver Tappe fDayNames[i] = fDate.ShortDayName(1 + (fStartOfWeek - 1 + i) % 7); 80378092ae7SKarsten Heimrich } 80478092ae7SKarsten Heimrich 80578092ae7SKarsten Heimrich 80678092ae7SKarsten Heimrich void 80778092ae7SKarsten Heimrich BCalendarView::_SetupDayNumbers() 80878092ae7SKarsten Heimrich { 8096846765fSOliver Tappe BDate startOfMonth(fDate.Year(), fDate.Month(), 1); 8106846765fSOliver Tappe if (!startOfMonth.IsValid()) 81178092ae7SKarsten Heimrich return; 81278092ae7SKarsten Heimrich 81378092ae7SKarsten Heimrich fFocusedDay.SetTo(0, 0); 81478092ae7SKarsten Heimrich fSelectedDay.SetTo(0, 0); 81578092ae7SKarsten Heimrich fNewFocusedDay.SetTo(0, 0); 81678092ae7SKarsten Heimrich 8176846765fSOliver Tappe const int32 daysInMonth = startOfMonth.DaysInMonth(); 8186846765fSOliver Tappe const int32 firstDayOffset 8196846765fSOliver Tappe = (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7; 82078092ae7SKarsten Heimrich 82178092ae7SKarsten Heimrich // calc the last day one month before 8226846765fSOliver Tappe BDate lastDayInMonthBefore(startOfMonth); 8236846765fSOliver Tappe lastDayInMonthBefore.AddDays(-1); 8246846765fSOliver Tappe const int32 lastDayBefore = lastDayInMonthBefore.DaysInMonth(); 82578092ae7SKarsten Heimrich 82678092ae7SKarsten Heimrich int32 counter = 0; 82778092ae7SKarsten Heimrich int32 firstDayAfter = 1; 82878092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 82978092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 8306846765fSOliver Tappe int32 day = 1 + counter - firstDayOffset; 8316846765fSOliver Tappe if (counter < firstDayOffset) 83278092ae7SKarsten Heimrich day += lastDayBefore; 8336846765fSOliver Tappe else if (counter >= firstDayOffset + daysInMonth) 83478092ae7SKarsten Heimrich day = firstDayAfter++; 8356846765fSOliver Tappe else if (day == fDate.Day()) { 83678092ae7SKarsten Heimrich fFocusedDay.SetTo(row, column); 83778092ae7SKarsten Heimrich fSelectedDay.SetTo(row, column); 83878092ae7SKarsten Heimrich fNewFocusedDay.SetTo(row, column); 83978092ae7SKarsten Heimrich } 84078092ae7SKarsten Heimrich counter++; 8416846765fSOliver Tappe fDayNumbers[row][column].Truncate(0); 84278092ae7SKarsten Heimrich fDayNumbers[row][column] << day; 84378092ae7SKarsten Heimrich } 84478092ae7SKarsten Heimrich } 84578092ae7SKarsten Heimrich } 84678092ae7SKarsten Heimrich 8476846765fSOliver Tappe 84878092ae7SKarsten Heimrich void 84978092ae7SKarsten Heimrich BCalendarView::_SetupWeekNumbers() 85078092ae7SKarsten Heimrich { 8516846765fSOliver Tappe BDate date(fDate.Year(), fDate.Month(), 1); 85278092ae7SKarsten Heimrich if (!date.IsValid()) 85378092ae7SKarsten Heimrich return; 85478092ae7SKarsten Heimrich 855c1ed5d75SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 85678092ae7SKarsten Heimrich fWeekNumbers[row].SetTo(""); 857f0932941SMichael Pfeiffer fWeekNumbers[row] << date.WeekNumber(); 858f0932941SMichael Pfeiffer date.AddDays(7); 859c1ed5d75SKarsten Heimrich } 86078092ae7SKarsten Heimrich } 86178092ae7SKarsten Heimrich 86278092ae7SKarsten Heimrich 86378092ae7SKarsten Heimrich void 86487663db4SOliver Tappe BCalendarView::_DrawDay(int32 currRow, int32 currColumn, int32 row, 86587663db4SOliver Tappe int32 column, int32 counter, BRect frame, const char* text, bool focus) 86678092ae7SKarsten Heimrich { 8676846765fSOliver Tappe BDate startOfMonth(fDate.Year(), fDate.Month(), 1); 8686846765fSOliver Tappe const int32 firstDayOffset 8696846765fSOliver Tappe = (7 + startOfMonth.DayOfWeek() - fStartOfWeek) % 7; 8706846765fSOliver Tappe const int32 daysMonth = startOfMonth.DaysInMonth(); 87178092ae7SKarsten Heimrich 87278092ae7SKarsten Heimrich bool enabled = true; 87378092ae7SKarsten Heimrich bool selected = false; 87478092ae7SKarsten Heimrich // check for the current date 87578092ae7SKarsten Heimrich if (currRow == row && currColumn == column) { 87678092ae7SKarsten Heimrich selected = true; // draw current date selected 8776846765fSOliver Tappe if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth) { 87878092ae7SKarsten Heimrich enabled = false; // days of month before or after 87978092ae7SKarsten Heimrich selected = false; // not selected but able to get focus 88078092ae7SKarsten Heimrich } 88178092ae7SKarsten Heimrich } else { 8826846765fSOliver Tappe if (counter <= firstDayOffset || counter > firstDayOffset + daysMonth) 88378092ae7SKarsten Heimrich enabled = false; // days of month before or after 88478092ae7SKarsten Heimrich } 88578092ae7SKarsten Heimrich 88678092ae7SKarsten Heimrich DrawDay(this, frame, text, selected, enabled, focus); 88778092ae7SKarsten Heimrich } 88878092ae7SKarsten Heimrich 88978092ae7SKarsten Heimrich 89078092ae7SKarsten Heimrich void 89178092ae7SKarsten Heimrich BCalendarView::_DrawDays() 89278092ae7SKarsten Heimrich { 89378092ae7SKarsten Heimrich BRect frame = _FirstCalendarItemFrame(); 89478092ae7SKarsten Heimrich 89578092ae7SKarsten Heimrich const int32 currRow = fSelectedDay.row; 89678092ae7SKarsten Heimrich const int32 currColumn = fSelectedDay.column; 89778092ae7SKarsten Heimrich 89878092ae7SKarsten Heimrich const bool isFocus = IsFocus(); 89978092ae7SKarsten Heimrich const int32 focusRow = fFocusedDay.row; 90078092ae7SKarsten Heimrich const int32 focusColumn = fFocusedDay.column; 90178092ae7SKarsten Heimrich 90278092ae7SKarsten Heimrich int32 counter = 0; 90378092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 90478092ae7SKarsten Heimrich BRect tmp = frame; 90578092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 90678092ae7SKarsten Heimrich counter++; 90778092ae7SKarsten Heimrich const char* day = fDayNumbers[row][column].String(); 90878092ae7SKarsten Heimrich bool focus = isFocus && focusRow == row && focusColumn == column; 90987663db4SOliver Tappe _DrawDay(currRow, currColumn, row, column, counter, tmp, day, 91087663db4SOliver Tappe focus); 91178092ae7SKarsten Heimrich 91278092ae7SKarsten Heimrich tmp.OffsetBy(tmp.Width(), 0.0); 91378092ae7SKarsten Heimrich } 91478092ae7SKarsten Heimrich frame.OffsetBy(0.0, frame.Height()); 91578092ae7SKarsten Heimrich } 91678092ae7SKarsten Heimrich } 91778092ae7SKarsten Heimrich 91878092ae7SKarsten Heimrich 91978092ae7SKarsten Heimrich void 92078092ae7SKarsten Heimrich BCalendarView::_DrawFocusRect() 92178092ae7SKarsten Heimrich { 92278092ae7SKarsten Heimrich BRect frame = _FirstCalendarItemFrame(); 92378092ae7SKarsten Heimrich 92478092ae7SKarsten Heimrich const int32 currRow = fSelectedDay.row; 92578092ae7SKarsten Heimrich const int32 currColumn = fSelectedDay.column; 92678092ae7SKarsten Heimrich 92778092ae7SKarsten Heimrich const int32 focusRow = fFocusedDay.row; 92878092ae7SKarsten Heimrich const int32 focusColumn = fFocusedDay.column; 92978092ae7SKarsten Heimrich 93078092ae7SKarsten Heimrich int32 counter = 0; 93178092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 93278092ae7SKarsten Heimrich BRect tmp = frame; 93378092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 93478092ae7SKarsten Heimrich counter++; 93578092ae7SKarsten Heimrich if (fNewFocusedDay.row == row && fNewFocusedDay.column == column) { 93678092ae7SKarsten Heimrich fFocusedDay.SetTo(row, column); 93778092ae7SKarsten Heimrich 93878092ae7SKarsten Heimrich bool focus = IsFocus() && true; 93978092ae7SKarsten Heimrich const char* day = fDayNumbers[row][column].String(); 94087663db4SOliver Tappe _DrawDay(currRow, currColumn, row, column, counter, tmp, day, 94187663db4SOliver Tappe focus); 9426846765fSOliver Tappe } else if (focusRow == row && focusColumn == column) { 94378092ae7SKarsten Heimrich const char* day = fDayNumbers[row][column].String(); 94487663db4SOliver Tappe _DrawDay(currRow, currColumn, row, column, counter, tmp, day, 94587663db4SOliver Tappe false); 94678092ae7SKarsten Heimrich } 94778092ae7SKarsten Heimrich tmp.OffsetBy(tmp.Width(), 0.0); 94878092ae7SKarsten Heimrich } 94978092ae7SKarsten Heimrich frame.OffsetBy(0.0, frame.Height()); 95078092ae7SKarsten Heimrich } 95178092ae7SKarsten Heimrich } 95278092ae7SKarsten Heimrich 95378092ae7SKarsten Heimrich 95478092ae7SKarsten Heimrich void 95578092ae7SKarsten Heimrich BCalendarView::_DrawDayHeader() 95678092ae7SKarsten Heimrich { 95778092ae7SKarsten Heimrich if (!fDayNameHeaderVisible) 95878092ae7SKarsten Heimrich return; 95978092ae7SKarsten Heimrich 96078092ae7SKarsten Heimrich int32 offset = 1; 96178092ae7SKarsten Heimrich int32 columns = 8; 96278092ae7SKarsten Heimrich if (!fWeekNumberHeaderVisible) { 96378092ae7SKarsten Heimrich offset = 0; 96478092ae7SKarsten Heimrich columns = 7; 96578092ae7SKarsten Heimrich } 96678092ae7SKarsten Heimrich 96778092ae7SKarsten Heimrich BRect frame = Bounds(); 96878092ae7SKarsten Heimrich frame.right = frame.Width() / columns - 1.0; 96978092ae7SKarsten Heimrich frame.bottom = frame.Height() / 7.0 - 2.0; 97078092ae7SKarsten Heimrich frame.OffsetBy(4.0, 4.0); 97178092ae7SKarsten Heimrich 97278092ae7SKarsten Heimrich for (int32 i = 0; i < columns; ++i) { 97378092ae7SKarsten Heimrich if (i == 0 && fWeekNumberHeaderVisible) { 97478092ae7SKarsten Heimrich DrawDayName(this, frame, ""); 97578092ae7SKarsten Heimrich frame.OffsetBy(frame.Width(), 0.0); 97678092ae7SKarsten Heimrich continue; 97778092ae7SKarsten Heimrich } 97878092ae7SKarsten Heimrich DrawDayName(this, frame, fDayNames[i - offset].String()); 97978092ae7SKarsten Heimrich frame.OffsetBy(frame.Width(), 0.0); 98078092ae7SKarsten Heimrich } 98178092ae7SKarsten Heimrich } 98278092ae7SKarsten Heimrich 98378092ae7SKarsten Heimrich 98478092ae7SKarsten Heimrich void 98578092ae7SKarsten Heimrich BCalendarView::_DrawWeekHeader() 98678092ae7SKarsten Heimrich { 98778092ae7SKarsten Heimrich if (!fWeekNumberHeaderVisible) 98878092ae7SKarsten Heimrich return; 98978092ae7SKarsten Heimrich 99078092ae7SKarsten Heimrich int32 rows = 7; 99178092ae7SKarsten Heimrich if (!fDayNameHeaderVisible) 99278092ae7SKarsten Heimrich rows = 6; 99378092ae7SKarsten Heimrich 99478092ae7SKarsten Heimrich BRect frame = Bounds(); 99578092ae7SKarsten Heimrich frame.right = frame.Width() / 8.0 - 2.0; 99678092ae7SKarsten Heimrich frame.bottom = frame.Height() / rows - 1.0; 99778092ae7SKarsten Heimrich 99878092ae7SKarsten Heimrich float offsetY = 4.0; 99978092ae7SKarsten Heimrich if (fDayNameHeaderVisible) 100078092ae7SKarsten Heimrich offsetY += frame.Height(); 100178092ae7SKarsten Heimrich 100278092ae7SKarsten Heimrich frame.OffsetBy(4.0, offsetY); 100378092ae7SKarsten Heimrich 100478092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 100578092ae7SKarsten Heimrich DrawWeekNumber(this, frame, fWeekNumbers[row].String()); 100678092ae7SKarsten Heimrich frame.OffsetBy(0.0, frame.Height()); 100778092ae7SKarsten Heimrich } 100878092ae7SKarsten Heimrich } 100978092ae7SKarsten Heimrich 101078092ae7SKarsten Heimrich 101178092ae7SKarsten Heimrich void 101278092ae7SKarsten Heimrich BCalendarView::_DrawItem(BView* owner, BRect frame, const char* text, 101378092ae7SKarsten Heimrich bool isSelected, bool isEnabled, bool focus) 101478092ae7SKarsten Heimrich { 101578092ae7SKarsten Heimrich rgb_color lColor = LowColor(); 101678092ae7SKarsten Heimrich rgb_color highColor = HighColor(); 101778092ae7SKarsten Heimrich 1018*99e015b4SJanus rgb_color textColor = ui_color(B_LIST_ITEM_TEXT_COLOR); 1019*99e015b4SJanus float tintDisabled = B_LIGHTEN_2_TINT; 1020*99e015b4SJanus 1021*99e015b4SJanus if (textColor.red + textColor.green + textColor.blue > 125 * 3) 1022*99e015b4SJanus tintDisabled = B_DARKEN_2_TINT; 102378092ae7SKarsten Heimrich 102478092ae7SKarsten Heimrich if (isSelected) { 1025*99e015b4SJanus SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR)); 1026*99e015b4SJanus textColor = ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR); 102778092ae7SKarsten Heimrich } else 1028*99e015b4SJanus SetHighColor(ui_color(B_LIST_BACKGROUND_COLOR)); 1029*99e015b4SJanus 1030*99e015b4SJanus SetLowColor(HighColor()); 103178092ae7SKarsten Heimrich 103278092ae7SKarsten Heimrich FillRect(frame.InsetByCopy(1.0, 1.0)); 103378092ae7SKarsten Heimrich 103478092ae7SKarsten Heimrich if (focus) { 103578092ae7SKarsten Heimrich SetHighColor(keyboard_navigation_color()); 103678092ae7SKarsten Heimrich StrokeRect(frame.InsetByCopy(1.0, 1.0)); 103778092ae7SKarsten Heimrich } 103878092ae7SKarsten Heimrich 1039*99e015b4SJanus SetHighColor(textColor); 104078092ae7SKarsten Heimrich if (!isEnabled) 1041*99e015b4SJanus SetHighColor(tint_color(textColor, tintDisabled)); 104278092ae7SKarsten Heimrich 104378092ae7SKarsten Heimrich float offsetH = frame.Width() / 2.0; 10446846765fSOliver Tappe float offsetV = frame.Height() / 2.0 + FontHeight(owner) / 2.0 - 2.0; 104578092ae7SKarsten Heimrich 10466846765fSOliver Tappe DrawString(text, BPoint(frame.right - offsetH - StringWidth(text) / 2.0, 10476846765fSOliver Tappe frame.top + offsetV)); 104878092ae7SKarsten Heimrich 104978092ae7SKarsten Heimrich SetLowColor(lColor); 105078092ae7SKarsten Heimrich SetHighColor(highColor); 105178092ae7SKarsten Heimrich } 105278092ae7SKarsten Heimrich 105378092ae7SKarsten Heimrich 105478092ae7SKarsten Heimrich void 105578092ae7SKarsten Heimrich BCalendarView::_UpdateSelection() 105678092ae7SKarsten Heimrich { 105778092ae7SKarsten Heimrich BRect frame = _FirstCalendarItemFrame(); 105878092ae7SKarsten Heimrich 105978092ae7SKarsten Heimrich const int32 currRow = fSelectedDay.row; 106078092ae7SKarsten Heimrich const int32 currColumn = fSelectedDay.column; 106178092ae7SKarsten Heimrich 106278092ae7SKarsten Heimrich const int32 focusRow = fFocusedDay.row; 106378092ae7SKarsten Heimrich const int32 focusColumn = fFocusedDay.column; 106478092ae7SKarsten Heimrich 106578092ae7SKarsten Heimrich int32 counter = 0; 106678092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 106778092ae7SKarsten Heimrich BRect tmp = frame; 106878092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 106978092ae7SKarsten Heimrich counter++; 107087663db4SOliver Tappe if (fNewSelectedDay.row == row 107187663db4SOliver Tappe && fNewSelectedDay.column == column) { 107278092ae7SKarsten Heimrich fSelectedDay.SetTo(row, column); 107378092ae7SKarsten Heimrich 107478092ae7SKarsten Heimrich const char* day = fDayNumbers[row][column].String(); 107587663db4SOliver Tappe bool focus = IsFocus() && focusRow == row 107687663db4SOliver Tappe && focusColumn == column; 107778092ae7SKarsten Heimrich _DrawDay(row, column, row, column, counter, tmp, day, focus); 10786846765fSOliver Tappe } else if (currRow == row && currColumn == column) { 107978092ae7SKarsten Heimrich const char* day = fDayNumbers[row][column].String(); 108087663db4SOliver Tappe bool focus = IsFocus() && focusRow == row 108187663db4SOliver Tappe && focusColumn == column; 108278092ae7SKarsten Heimrich _DrawDay(currRow, currColumn, -1, -1, counter, tmp, day, focus); 108378092ae7SKarsten Heimrich } 108478092ae7SKarsten Heimrich tmp.OffsetBy(tmp.Width(), 0.0); 108578092ae7SKarsten Heimrich } 108678092ae7SKarsten Heimrich frame.OffsetBy(0.0, frame.Height()); 108778092ae7SKarsten Heimrich } 108878092ae7SKarsten Heimrich } 108978092ae7SKarsten Heimrich 109078092ae7SKarsten Heimrich 109178092ae7SKarsten Heimrich BRect 109278092ae7SKarsten Heimrich BCalendarView::_FirstCalendarItemFrame() const 109378092ae7SKarsten Heimrich { 109478092ae7SKarsten Heimrich int32 rows = 7; 109578092ae7SKarsten Heimrich int32 columns = 8; 109678092ae7SKarsten Heimrich 109778092ae7SKarsten Heimrich if (!fDayNameHeaderVisible) 109878092ae7SKarsten Heimrich rows = 6; 109978092ae7SKarsten Heimrich 110078092ae7SKarsten Heimrich if (!fWeekNumberHeaderVisible) 110178092ae7SKarsten Heimrich columns = 7; 110278092ae7SKarsten Heimrich 110378092ae7SKarsten Heimrich BRect frame = Bounds(); 110478092ae7SKarsten Heimrich frame.right = frame.Width() / columns - 1.0; 110578092ae7SKarsten Heimrich frame.bottom = frame.Height() / rows - 1.0; 110678092ae7SKarsten Heimrich 110778092ae7SKarsten Heimrich float offsetY = 4.0; 110878092ae7SKarsten Heimrich if (fDayNameHeaderVisible) 110978092ae7SKarsten Heimrich offsetY += frame.Height(); 111078092ae7SKarsten Heimrich 111178092ae7SKarsten Heimrich float offsetX = 4.0; 111278092ae7SKarsten Heimrich if (fWeekNumberHeaderVisible) 111378092ae7SKarsten Heimrich offsetX += frame.Width(); 111478092ae7SKarsten Heimrich 111578092ae7SKarsten Heimrich return frame.OffsetBySelf(offsetX, offsetY); 111678092ae7SKarsten Heimrich } 111778092ae7SKarsten Heimrich 111878092ae7SKarsten Heimrich 111978092ae7SKarsten Heimrich BRect 112078092ae7SKarsten Heimrich BCalendarView::_SetNewSelectedDay(const BPoint& where) 112178092ae7SKarsten Heimrich { 112278092ae7SKarsten Heimrich BRect frame = _FirstCalendarItemFrame(); 112378092ae7SKarsten Heimrich 112478092ae7SKarsten Heimrich int32 counter = 0; 112578092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 112678092ae7SKarsten Heimrich BRect tmp = frame; 112778092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 112878092ae7SKarsten Heimrich counter++; 112978092ae7SKarsten Heimrich if (tmp.Contains(where)) { 113078092ae7SKarsten Heimrich fNewSelectedDay.SetTo(row, column); 11316846765fSOliver Tappe int32 year; 11326846765fSOliver Tappe int32 month; 11336846765fSOliver Tappe _GetYearMonthForSelection(fNewSelectedDay, &year, &month); 11346846765fSOliver Tappe if (month == fDate.Month()) { 11356846765fSOliver Tappe // only change date if a day in the current month has been 11366846765fSOliver Tappe // selected 11376846765fSOliver Tappe int32 day = atoi(fDayNumbers[row][column].String()); 11386846765fSOliver Tappe fDate.SetDate(year, month, day); 11396846765fSOliver Tappe } 114078092ae7SKarsten Heimrich return tmp; 114178092ae7SKarsten Heimrich } 114278092ae7SKarsten Heimrich tmp.OffsetBy(tmp.Width(), 0.0); 114378092ae7SKarsten Heimrich } 114478092ae7SKarsten Heimrich frame.OffsetBy(0.0, frame.Height()); 114578092ae7SKarsten Heimrich } 114678092ae7SKarsten Heimrich 114778092ae7SKarsten Heimrich return frame; 114878092ae7SKarsten Heimrich } 114978092ae7SKarsten Heimrich 115078092ae7SKarsten Heimrich 115178092ae7SKarsten Heimrich BRect 115278092ae7SKarsten Heimrich BCalendarView::_RectOfDay(const Selection& selection) const 115378092ae7SKarsten Heimrich { 115478092ae7SKarsten Heimrich BRect frame = _FirstCalendarItemFrame(); 115578092ae7SKarsten Heimrich 115678092ae7SKarsten Heimrich int32 counter = 0; 115778092ae7SKarsten Heimrich for (int32 row = 0; row < 6; ++row) { 115878092ae7SKarsten Heimrich BRect tmp = frame; 115978092ae7SKarsten Heimrich for (int32 column = 0; column < 7; ++column) { 116078092ae7SKarsten Heimrich counter++; 11616846765fSOliver Tappe if (selection.row == row && selection.column == column) 116278092ae7SKarsten Heimrich return tmp; 116378092ae7SKarsten Heimrich tmp.OffsetBy(tmp.Width(), 0.0); 116478092ae7SKarsten Heimrich } 116578092ae7SKarsten Heimrich frame.OffsetBy(0.0, frame.Height()); 116678092ae7SKarsten Heimrich } 116778092ae7SKarsten Heimrich 116878092ae7SKarsten Heimrich return frame; 116978092ae7SKarsten Heimrich } 117078092ae7SKarsten Heimrich 117178092ae7SKarsten Heimrich 117278092ae7SKarsten Heimrich } // namespace BPrivate 1173