2 * Copyright 2007-2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Julun <host.haiku@gmx.de>
10 #include "CalendarView.h"
14 #include <DateFormat.h>
15 #include <LayoutUtils.h>
23 FontHeight(const BView
* view
)
31 font
.GetHeight(&fheight
);
32 return ceilf(fheight
.ascent
+ fheight
.descent
+ fheight
.leading
);
39 BCalendarView::BCalendarView(BRect frame
, const char* name
, uint32 resizeMask
,
42 BView(frame
, name
, resizeMask
, flags
),
44 fSelectionMessage(NULL
),
46 fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME
)),
48 fSelectionChanged(false),
49 fCurrentDayChanged(false),
50 fStartOfWeek((int32
)B_WEEKDAY_MONDAY
),
51 fDayNameHeaderVisible(true),
52 fWeekNumberHeaderVisible(true)
58 BCalendarView::BCalendarView(const char* name
, uint32 flags
)
62 fSelectionMessage(NULL
),
64 fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME
)),
66 fSelectionChanged(false),
67 fCurrentDayChanged(false),
68 fStartOfWeek((int32
)B_WEEKDAY_MONDAY
),
69 fDayNameHeaderVisible(true),
70 fWeekNumberHeaderVisible(true)
76 BCalendarView::~BCalendarView()
78 SetSelectionMessage(NULL
);
82 BCalendarView::BCalendarView(BMessage
* archive
)
86 fSelectionMessage(NULL
),
88 fCurrentDate(BDate::CurrentDate(B_LOCAL_TIME
)),
90 fSelectionChanged(false),
91 fCurrentDayChanged(false),
92 fStartOfWeek((int32
)B_WEEKDAY_MONDAY
),
93 fDayNameHeaderVisible(true),
94 fWeekNumberHeaderVisible(true)
96 if (archive
->HasMessage("_invokeMsg")) {
97 BMessage
* invokationMessage
= new BMessage
;
98 archive
->FindMessage("_invokeMsg", invokationMessage
);
99 SetInvocationMessage(invokationMessage
);
102 if (archive
->HasMessage("_selectMsg")) {
103 BMessage
* selectionMessage
= new BMessage
;
104 archive
->FindMessage("selectMsg", selectionMessage
);
105 SetSelectionMessage(selectionMessage
);
108 if (archive
->FindInt32("_weekStart", &fStartOfWeek
) != B_OK
)
109 fStartOfWeek
= (int32
)B_WEEKDAY_MONDAY
;
111 if (archive
->FindBool("_dayHeader", &fDayNameHeaderVisible
) != B_OK
)
112 fDayNameHeaderVisible
= true;
114 if (archive
->FindBool("_weekHeader", &fWeekNumberHeaderVisible
) != B_OK
)
115 fWeekNumberHeaderVisible
= true;
124 BCalendarView::Instantiate(BMessage
* archive
)
126 if (validate_instantiation(archive
, "BCalendarView"))
127 return new BCalendarView(archive
);
134 BCalendarView::Archive(BMessage
* archive
, bool deep
) const
136 status_t status
= BView::Archive(archive
, deep
);
138 if (status
== B_OK
&& InvocationMessage())
139 status
= archive
->AddMessage("_invokeMsg", InvocationMessage());
141 if (status
== B_OK
&& SelectionMessage())
142 status
= archive
->AddMessage("_selectMsg", SelectionMessage());
145 status
= fDate
.Archive(archive
);
148 status
= archive
->AddInt32("_weekStart", fStartOfWeek
);
151 status
= archive
->AddBool("_dayHeader", fDayNameHeaderVisible
);
154 status
= archive
->AddBool("_weekHeader", fWeekNumberHeaderVisible
);
161 BCalendarView::AttachedToWindow()
163 BView::AttachedToWindow();
165 if (!Messenger().IsValid())
166 SetTarget(Window(), NULL
);
168 SetViewUIColor(B_LIST_BACKGROUND_COLOR
);
173 BCalendarView::FrameResized(float width
, float height
)
176 Invalidate(Bounds());
181 BCalendarView::Draw(BRect updateRect
)
190 if (fSelectionChanged
) {
196 if (fCurrentDayChanged
) {
206 rgb_color background
= ui_color(B_PANEL_BACKGROUND_COLOR
);
207 SetHighColor(tint_color(background
, B_DARKEN_3_TINT
));
208 StrokeRect(Bounds());
216 BCalendarView::DrawDay(BView
* owner
, BRect frame
, const char* text
,
217 bool isSelected
, bool isEnabled
, bool focus
, bool highlight
)
219 _DrawItem(owner
, frame
, text
, isSelected
, isEnabled
, focus
, highlight
);
224 BCalendarView::DrawDayName(BView
* owner
, BRect frame
, const char* text
)
226 // we get the full rect, fake this as the internal function
227 // shrinks the frame to work properly when drawing a day item
228 _DrawItem(owner
, frame
.InsetByCopy(-1.0, -1.0), text
, true);
233 BCalendarView::DrawWeekNumber(BView
* owner
, BRect frame
, const char* text
)
235 // we get the full rect, fake this as the internal function
236 // shrinks the frame to work properly when drawing a day item
237 _DrawItem(owner
, frame
.InsetByCopy(-1.0, -1.0), text
, true);
242 BCalendarView::SelectionCommand() const
244 if (SelectionMessage())
245 return SelectionMessage()->what
;
252 BCalendarView::SelectionMessage() const
254 return fSelectionMessage
;
259 BCalendarView::SetSelectionMessage(BMessage
* message
)
261 delete fSelectionMessage
;
262 fSelectionMessage
= message
;
267 BCalendarView::InvocationCommand() const
269 return BInvoker::Command();
274 BCalendarView::InvocationMessage() const
276 return BInvoker::Message();
281 BCalendarView::SetInvocationMessage(BMessage
* message
)
283 BInvoker::SetMessage(message
);
288 BCalendarView::MakeFocus(bool state
)
290 if (IsFocus() == state
)
293 BView::MakeFocus(state
);
295 // TODO: solve this better
296 fFocusChanged
= true;
297 Draw(_RectOfDay(fFocusedDay
));
298 fFocusChanged
= false;
303 BCalendarView::Invoke(BMessage
* message
)
306 uint32 kind
= InvokeKind(¬ify
);
308 BMessage
clone(kind
);
309 status_t status
= B_BAD_VALUE
;
311 if (!message
&& !notify
)
320 clone
.AddPointer("source", this);
321 clone
.AddInt64("when", (int64
)system_time());
322 clone
.AddMessenger("be:sender", BMessenger(this));
326 _GetYearMonthForSelection(fSelectedDay
, &year
, &month
);
328 clone
.AddInt32("year", fDate
.Year());
329 clone
.AddInt32("month", fDate
.Month());
330 clone
.AddInt32("day", fDate
.Day());
333 status
= BInvoker::Invoke(&clone
);
335 SendNotices(kind
, &clone
);
342 BCalendarView::MouseDown(BPoint where
)
347 Window()->UpdateIfNeeded();
350 BRect frame
= Bounds();
351 if (fDayNameHeaderVisible
)
352 frame
.top
+= frame
.Height() / 7 - 1.0;
354 if (fWeekNumberHeaderVisible
)
355 frame
.left
+= frame
.Width() / 8 - 1.0;
357 if (!frame
.Contains(where
))
360 // try to set to new day
361 frame
= _SetNewSelectedDay(where
);
364 if (fSelectedDay
!= fNewSelectedDay
) {
366 fFocusChanged
= true;
367 fNewFocusedDay
= fNewSelectedDay
;
368 Draw(_RectOfDay(fFocusedDay
));
369 fFocusChanged
= false;
372 fSelectionChanged
= true;
374 Draw(_RectOfDay(fSelectedDay
));
375 fSelectionChanged
= false;
377 // notify that selection changed
378 InvokeNotify(SelectionMessage(), B_CONTROL_MODIFIED
);
382 // on double click invoke
383 BMessage
* message
= Looper()->CurrentMessage();
384 if (message
->FindInt32("clicks", &clicks
) == B_OK
&& clicks
> 1)
390 BCalendarView::KeyDown(const char* bytes
, int32 numBytes
)
392 const int32 kRows
= 6;
393 const int32 kColumns
= 7;
395 int32 row
= fFocusedDay
.row
;
396 int32 column
= fFocusedDay
.column
;
402 column
= kColumns
- 1;
405 fFocusChanged
= true;
407 fFocusChanged
= true;
412 if (column
== kColumns
) {
416 fFocusChanged
= true;
418 fFocusChanged
= true;
424 fFocusChanged
= true;
430 fFocusChanged
= true;
456 fSelectionChanged
= true;
457 BPoint pt
= _RectOfDay(fFocusedDay
).LeftTop();
458 Draw(_SetNewSelectedDay(pt
+ BPoint(4.0, 4.0)));
459 Draw(_RectOfDay(fSelectedDay
));
460 fSelectionChanged
= false;
467 BView::KeyDown(bytes
, numBytes
);
472 fNewFocusedDay
.SetTo(row
, column
);
473 Draw(_RectOfDay(fFocusedDay
));
474 Draw(_RectOfDay(fNewFocusedDay
));
475 fFocusChanged
= false;
481 BCalendarView::Pulse()
483 _UpdateCurrentDate();
488 BCalendarView::ResizeToPreferred()
493 GetPreferredSize(&width
, &height
);
494 BView::ResizeTo(width
, height
);
499 BCalendarView::GetPreferredSize(float* width
, float* height
)
501 _GetPreferredSize(width
, height
);
506 BCalendarView::MaxSize()
508 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
509 BSize(B_SIZE_UNLIMITED
, B_SIZE_UNLIMITED
));
514 BCalendarView::MinSize()
517 _GetPreferredSize(&width
, &height
);
518 return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(width
, height
));
523 BCalendarView::PreferredSize()
525 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
530 BCalendarView::Day() const
537 BCalendarView::Year() const
540 _GetYearMonthForSelection(fSelectedDay
, &year
, NULL
);
547 BCalendarView::Month() const
550 _GetYearMonthForSelection(fSelectedDay
, NULL
, &month
);
557 BCalendarView::SetDay(int32 day
)
569 BCalendarView::SetMonth(int32 month
)
571 if (month
< 1 || month
> 12)
574 int32 oldDay
= date
.Day();
576 date
.SetMonth(month
);
577 date
.SetDay(1); // make sure the date is valid
579 // We must make sure that the day in month fits inside the new month.
580 if (oldDay
> date
.DaysInMonth())
581 date
.SetDay(date
.DaysInMonth());
590 BCalendarView::SetYear(int32 year
)
594 // This can fail when going from 29 feb. on a leap year to a non-leap year.
595 if (date
.Month() == 2 && date
.Day() == 29 && !date
.IsLeapYear(year
))
598 // TODO we should also handle the "hole" at the switch between Julian and
599 // Gregorian calendars, which will result in an invalid date.
608 BCalendarView::Date() const
612 _GetYearMonthForSelection(fSelectedDay
, &year
, &month
);
613 return BDate(year
, month
, fDate
.Day());
618 BCalendarView::SetDate(const BDate
& date
)
626 if (fDate
.Year() == date
.Year() && fDate
.Month() == date
.Month()) {
631 fFocusChanged
= true;
632 Draw(_RectOfDay(fFocusedDay
));
633 fFocusChanged
= false;
636 fSelectionChanged
= true;
637 Draw(_RectOfDay(fSelectedDay
));
638 Draw(_RectOfDay(fNewSelectedDay
));
639 fSelectionChanged
= false;
646 BRect frame
= Bounds();
647 if (fDayNameHeaderVisible
)
648 frame
.top
+= frame
.Height() / 7 - 1.0;
650 if (fWeekNumberHeaderVisible
)
651 frame
.left
+= frame
.Width() / 8 - 1.0;
653 Draw(frame
.InsetBySelf(4.0, 4.0));
661 BCalendarView::SetDate(int32 year
, int32 month
, int32 day
)
663 return SetDate(BDate(year
, month
, day
));
668 BCalendarView::StartOfWeek() const
670 return BWeekday(fStartOfWeek
);
675 BCalendarView::SetStartOfWeek(BWeekday startOfWeek
)
677 if (fStartOfWeek
== (int32
)startOfWeek
)
680 fStartOfWeek
= (int32
)startOfWeek
;
686 Invalidate(Bounds().InsetBySelf(1.0, 1.0));
691 BCalendarView::IsDayNameHeaderVisible() const
693 return fDayNameHeaderVisible
;
698 BCalendarView::SetDayNameHeaderVisible(bool visible
)
700 if (fDayNameHeaderVisible
== visible
)
703 fDayNameHeaderVisible
= visible
;
704 Invalidate(Bounds().InsetBySelf(1.0, 1.0));
709 BCalendarView::UpdateDayNameHeader()
711 if (!fDayNameHeaderVisible
)
715 Invalidate(Bounds().InsetBySelf(1.0, 1.0));
720 BCalendarView::IsWeekNumberHeaderVisible() const
722 return fWeekNumberHeaderVisible
;
727 BCalendarView::SetWeekNumberHeaderVisible(bool visible
)
729 if (fWeekNumberHeaderVisible
== visible
)
732 fWeekNumberHeaderVisible
= visible
;
733 Invalidate(Bounds().InsetBySelf(1.0, 1.0));
738 BCalendarView::_InitObject()
740 fDate
= BDate::CurrentDate(B_LOCAL_TIME
);
742 BDateFormat().GetStartOfWeek((BWeekday
*)&fStartOfWeek
);
751 BCalendarView::_SetToDay()
753 BDate
date(fDate
.Year(), fDate
.Month(), 1);
757 const int32 firstDayOffset
= (7 + date
.DayOfWeek() - fStartOfWeek
) % 7;
759 int32 day
= 1 - firstDayOffset
;
760 for (int32 row
= 0; row
< 6; ++row
) {
761 for (int32 column
= 0; column
< 7; ++column
) {
762 if (day
== fDate
.Day()) {
763 fNewFocusedDay
.SetTo(row
, column
);
764 fNewSelectedDay
.SetTo(row
, column
);
771 fNewFocusedDay
.SetTo(0, 0);
772 fNewSelectedDay
.SetTo(0, 0);
777 BCalendarView::_SetToCurrentDay()
779 BDate
date(fCurrentDate
.Year(), fCurrentDate
.Month(), 1);
782 if (fDate
.Year() != date
.Year() || fDate
.Month() != date
.Month()) {
783 fNewCurrentDay
.SetTo(-1, -1);
786 const int32 firstDayOffset
= (7 + date
.DayOfWeek() - fStartOfWeek
) % 7;
788 int32 day
= 1 - firstDayOffset
;
789 for (int32 row
= 0; row
< 6; ++row
) {
790 for (int32 column
= 0; column
< 7; ++column
) {
791 if (day
== fCurrentDate
.Day()) {
792 fNewCurrentDay
.SetTo(row
, column
);
799 fNewCurrentDay
.SetTo(-1, -1);
804 BCalendarView::_GetYearMonthForSelection(const Selection
& selection
,
805 int32
* year
, int32
* month
) const
807 BDate
startOfMonth(fDate
.Year(), fDate
.Month(), 1);
808 const int32 firstDayOffset
809 = (7 + startOfMonth
.DayOfWeek() - fStartOfWeek
) % 7;
810 const int32 daysInMonth
= startOfMonth
.DaysInMonth();
813 const int32 dayOffset
= selection
.row
* 7 + selection
.column
;
814 if (dayOffset
< firstDayOffset
)
816 else if (dayOffset
>= firstDayOffset
+ daysInMonth
)
821 *month
= date
.Month();
826 BCalendarView::_GetPreferredSize(float* _width
, float* _height
)
830 font_height fontHeight
;
831 font
.GetHeight(&fontHeight
);
833 const float height
= FontHeight(this) + 4.0;
836 if (!fDayNameHeaderVisible
)
839 // height = font height * rows + 8 px border
840 *_height
= height
* rows
+ 8.0;
843 for (int32 column
= 0; column
< 7; ++column
) {
844 float tmp
= StringWidth(fDayNames
[column
].String()) + 2.0;
845 width
= tmp
> width
? tmp
: width
;
849 if (!fWeekNumberHeaderVisible
)
852 // width = max width day name * 8 column + 8 px border
853 *_width
= width
* columns
+ 8.0;
858 BCalendarView::_SetupDayNames()
860 BDateFormatStyle style
= B_LONG_DATE_FORMAT
;
862 while (style
!= B_DATE_FORMAT_STYLE_COUNT
) {
863 _PopulateDayNames(style
);
864 GetPreferredSize(&width
, &height
);
865 if (width
< Bounds().Width())
867 style
= static_cast<BDateFormatStyle
>(static_cast<int>(style
) + 1);
873 BCalendarView::_PopulateDayNames(BDateFormatStyle style
)
875 for (int32 i
= 0; i
<= 6; ++i
) {
877 BDateFormat().GetDayName(1 + (fStartOfWeek
- 1 + i
) % 7,
878 fDayNames
[i
], style
);
884 BCalendarView::_SetupDayNumbers()
886 BDate
startOfMonth(fDate
.Year(), fDate
.Month(), 1);
887 if (!startOfMonth
.IsValid())
890 fFocusedDay
.SetTo(0, 0);
891 fSelectedDay
.SetTo(0, 0);
892 fNewFocusedDay
.SetTo(0, 0);
893 fCurrentDay
.SetTo(-1, -1);
895 const int32 daysInMonth
= startOfMonth
.DaysInMonth();
896 const int32 firstDayOffset
897 = (7 + startOfMonth
.DayOfWeek() - fStartOfWeek
) % 7;
899 // calc the last day one month before
900 BDate
lastDayInMonthBefore(startOfMonth
);
901 lastDayInMonthBefore
.AddDays(-1);
902 const int32 lastDayBefore
= lastDayInMonthBefore
.DaysInMonth();
905 int32 firstDayAfter
= 1;
906 for (int32 row
= 0; row
< 6; ++row
) {
907 for (int32 column
= 0; column
< 7; ++column
) {
908 int32 day
= 1 + counter
- firstDayOffset
;
909 if (counter
< firstDayOffset
)
910 day
+= lastDayBefore
;
911 else if (counter
>= firstDayOffset
+ daysInMonth
)
912 day
= firstDayAfter
++;
913 else if (day
== fDate
.Day()) {
914 fFocusedDay
.SetTo(row
, column
);
915 fSelectedDay
.SetTo(row
, column
);
916 fNewFocusedDay
.SetTo(row
, column
);
918 if (day
== fCurrentDate
.Day() && counter
>= firstDayOffset
919 && counter
< firstDayOffset
+ daysInMonth
920 && fDate
.Month() == fCurrentDate
.Month()
921 && fDate
.Year() == fCurrentDate
.Year())
922 fCurrentDay
.SetTo(row
, column
);
925 fDayNumbers
[row
][column
].Truncate(0);
926 fDayNumbers
[row
][column
] << day
;
933 BCalendarView::_SetupWeekNumbers()
935 BDate
date(fDate
.Year(), fDate
.Month(), 1);
939 for (int32 row
= 0; row
< 6; ++row
) {
940 fWeekNumbers
[row
].SetTo("");
941 fWeekNumbers
[row
] << date
.WeekNumber();
948 BCalendarView::_DrawDay(int32 currRow
, int32 currColumn
, int32 row
,
949 int32 column
, int32 counter
, BRect frame
, const char* text
,
950 bool focus
, bool highlight
)
952 BDate
startOfMonth(fDate
.Year(), fDate
.Month(), 1);
953 const int32 firstDayOffset
954 = (7 + startOfMonth
.DayOfWeek() - fStartOfWeek
) % 7;
955 const int32 daysMonth
= startOfMonth
.DaysInMonth();
958 bool selected
= false;
959 // check for the current date
960 if (currRow
== row
&& currColumn
== column
) {
961 selected
= true; // draw current date selected
962 if (counter
<= firstDayOffset
|| counter
> firstDayOffset
+ daysMonth
) {
963 enabled
= false; // days of month before or after
964 selected
= false; // not selected but able to get focus
967 if (counter
<= firstDayOffset
|| counter
> firstDayOffset
+ daysMonth
)
968 enabled
= false; // days of month before or after
971 DrawDay(this, frame
, text
, selected
, enabled
, focus
, highlight
);
976 BCalendarView::_DrawDays()
978 BRect frame
= _FirstCalendarItemFrame();
980 const int32 currRow
= fSelectedDay
.row
;
981 const int32 currColumn
= fSelectedDay
.column
;
983 const bool isFocus
= IsFocus();
984 const int32 focusRow
= fFocusedDay
.row
;
985 const int32 focusColumn
= fFocusedDay
.column
;
987 const int32 highlightRow
= fCurrentDay
.row
;
988 const int32 highlightColumn
= fCurrentDay
.column
;
991 for (int32 row
= 0; row
< 6; ++row
) {
993 for (int32 column
= 0; column
< 7; ++column
) {
995 const char* day
= fDayNumbers
[row
][column
].String();
996 bool focus
= isFocus
&& focusRow
== row
&& focusColumn
== column
;
997 bool highlight
= highlightRow
== row
&& highlightColumn
== column
;
998 _DrawDay(currRow
, currColumn
, row
, column
, counter
, tmp
, day
,
1001 tmp
.OffsetBy(tmp
.Width(), 0.0);
1003 frame
.OffsetBy(0.0, frame
.Height());
1009 BCalendarView::_DrawFocusRect()
1011 BRect frame
= _FirstCalendarItemFrame();
1013 const int32 currRow
= fSelectedDay
.row
;
1014 const int32 currColumn
= fSelectedDay
.column
;
1016 const int32 focusRow
= fFocusedDay
.row
;
1017 const int32 focusColumn
= fFocusedDay
.column
;
1019 const int32 highlightRow
= fCurrentDay
.row
;
1020 const int32 highlightColumn
= fCurrentDay
.column
;
1023 for (int32 row
= 0; row
< 6; ++row
) {
1025 for (int32 column
= 0; column
< 7; ++column
) {
1027 if (fNewFocusedDay
.row
== row
&& fNewFocusedDay
.column
== column
) {
1028 fFocusedDay
.SetTo(row
, column
);
1030 bool focus
= IsFocus() && true;
1031 bool highlight
= highlightRow
== row
&& highlightColumn
== column
;
1032 const char* day
= fDayNumbers
[row
][column
].String();
1033 _DrawDay(currRow
, currColumn
, row
, column
, counter
, tmp
, day
,
1035 } else if (focusRow
== row
&& focusColumn
== column
) {
1036 const char* day
= fDayNumbers
[row
][column
].String();
1037 bool highlight
= highlightRow
== row
&& highlightColumn
== column
;
1038 _DrawDay(currRow
, currColumn
, row
, column
, counter
, tmp
, day
,
1041 tmp
.OffsetBy(tmp
.Width(), 0.0);
1043 frame
.OffsetBy(0.0, frame
.Height());
1049 BCalendarView::_DrawDayHeader()
1051 if (!fDayNameHeaderVisible
)
1056 if (!fWeekNumberHeaderVisible
) {
1061 BRect frame
= Bounds();
1062 frame
.right
= frame
.Width() / columns
- 1.0;
1063 frame
.bottom
= frame
.Height() / 7.0 - 2.0;
1064 frame
.OffsetBy(4.0, 4.0);
1066 for (int32 i
= 0; i
< columns
; ++i
) {
1067 if (i
== 0 && fWeekNumberHeaderVisible
) {
1068 DrawDayName(this, frame
, "");
1069 frame
.OffsetBy(frame
.Width(), 0.0);
1072 DrawDayName(this, frame
, fDayNames
[i
- offset
].String());
1073 frame
.OffsetBy(frame
.Width(), 0.0);
1079 BCalendarView::_DrawWeekHeader()
1081 if (!fWeekNumberHeaderVisible
)
1085 if (!fDayNameHeaderVisible
)
1088 BRect frame
= Bounds();
1089 frame
.right
= frame
.Width() / 8.0 - 2.0;
1090 frame
.bottom
= frame
.Height() / rows
- 1.0;
1092 float offsetY
= 4.0;
1093 if (fDayNameHeaderVisible
)
1094 offsetY
+= frame
.Height();
1096 frame
.OffsetBy(4.0, offsetY
);
1098 for (int32 row
= 0; row
< 6; ++row
) {
1099 DrawWeekNumber(this, frame
, fWeekNumbers
[row
].String());
1100 frame
.OffsetBy(0.0, frame
.Height());
1106 BCalendarView::_DrawItem(BView
* owner
, BRect frame
, const char* text
,
1107 bool isSelected
, bool isEnabled
, bool focus
, bool isHighlight
)
1109 rgb_color lColor
= LowColor();
1110 rgb_color highColor
= HighColor();
1112 rgb_color textColor
= ui_color(B_LIST_ITEM_TEXT_COLOR
);
1113 rgb_color bgColor
= ui_color(B_LIST_BACKGROUND_COLOR
);
1114 float tintDisabled
= B_LIGHTEN_2_TINT
;
1115 float tintHighlight
= B_LIGHTEN_1_TINT
;
1117 if (textColor
.red
+ textColor
.green
+ textColor
.blue
> 125 * 3)
1118 tintDisabled
= B_DARKEN_2_TINT
;
1120 if (bgColor
.red
+ bgColor
.green
+ bgColor
.blue
> 125 * 3)
1121 tintHighlight
= B_DARKEN_1_TINT
;
1124 SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR
));
1125 textColor
= ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR
);
1126 } else if (isHighlight
)
1127 SetHighColor(tint_color(bgColor
, tintHighlight
));
1129 SetHighColor(bgColor
);
1131 SetLowColor(HighColor());
1133 FillRect(frame
.InsetByCopy(1.0, 1.0));
1136 rgb_color focusColor
= keyboard_navigation_color();
1137 SetHighColor(focusColor
);
1138 StrokeRect(frame
.InsetByCopy(1.0, 1.0));
1141 textColor
= focusColor
;
1144 SetHighColor(textColor
);
1146 SetHighColor(tint_color(textColor
, tintDisabled
));
1148 float offsetH
= frame
.Width() / 2.0;
1149 float offsetV
= frame
.Height() / 2.0 + FontHeight(owner
) / 2.0 - 2.0;
1151 BFont
font(be_plain_font
);
1153 font
.SetFace(B_BOLD_FACE
);
1155 font
.SetFace(B_REGULAR_FACE
);
1158 DrawString(text
, BPoint(frame
.right
- offsetH
- StringWidth(text
) / 2.0,
1159 frame
.top
+ offsetV
));
1161 SetLowColor(lColor
);
1162 SetHighColor(highColor
);
1167 BCalendarView::_UpdateSelection()
1169 BRect frame
= _FirstCalendarItemFrame();
1171 const int32 currRow
= fSelectedDay
.row
;
1172 const int32 currColumn
= fSelectedDay
.column
;
1174 const int32 focusRow
= fFocusedDay
.row
;
1175 const int32 focusColumn
= fFocusedDay
.column
;
1177 const int32 highlightRow
= fCurrentDay
.row
;
1178 const int32 highlightColumn
= fCurrentDay
.column
;
1181 for (int32 row
= 0; row
< 6; ++row
) {
1183 for (int32 column
= 0; column
< 7; ++column
) {
1185 if (fNewSelectedDay
.row
== row
1186 && fNewSelectedDay
.column
== column
) {
1187 fSelectedDay
.SetTo(row
, column
);
1189 const char* day
= fDayNumbers
[row
][column
].String();
1190 bool focus
= IsFocus() && focusRow
== row
1191 && focusColumn
== column
;
1192 bool highlight
= highlightRow
== row
&& highlightColumn
== column
;
1193 _DrawDay(row
, column
, row
, column
, counter
, tmp
, day
, focus
, highlight
);
1194 } else if (currRow
== row
&& currColumn
== column
) {
1195 const char* day
= fDayNumbers
[row
][column
].String();
1196 bool focus
= IsFocus() && focusRow
== row
1197 && focusColumn
== column
;
1198 bool highlight
= highlightRow
== row
&& highlightColumn
== column
;
1199 _DrawDay(currRow
, currColumn
, -1, -1, counter
, tmp
, day
, focus
, highlight
);
1201 tmp
.OffsetBy(tmp
.Width(), 0.0);
1203 frame
.OffsetBy(0.0, frame
.Height());
1209 BCalendarView::_UpdateCurrentDay()
1211 BRect frame
= _FirstCalendarItemFrame();
1213 const int32 selectRow
= fSelectedDay
.row
;
1214 const int32 selectColumn
= fSelectedDay
.column
;
1216 const int32 focusRow
= fFocusedDay
.row
;
1217 const int32 focusColumn
= fFocusedDay
.column
;
1219 const int32 currRow
= fCurrentDay
.row
;
1220 const int32 currColumn
= fCurrentDay
.column
;
1223 for (int32 row
= 0; row
< 6; ++row
) {
1225 for (int32 column
= 0; column
< 7; ++column
) {
1227 if (fNewCurrentDay
.row
== row
1228 && fNewCurrentDay
.column
== column
) {
1229 fCurrentDay
.SetTo(row
, column
);
1231 const char* day
= fDayNumbers
[row
][column
].String();
1232 bool focus
= IsFocus() && focusRow
== row
1233 && focusColumn
== column
;
1234 bool isSelected
= selectRow
== row
&& selectColumn
== column
;
1236 _DrawDay(row
, column
, row
, column
, counter
, tmp
, day
, focus
, true);
1238 _DrawDay(row
, column
, -1, -1, counter
, tmp
, day
, focus
, true);
1240 } else if (currRow
== row
&& currColumn
== column
) {
1241 const char* day
= fDayNumbers
[row
][column
].String();
1242 bool focus
= IsFocus() && focusRow
== row
1243 && focusColumn
== column
;
1244 bool isSelected
= selectRow
== row
&& selectColumn
== column
;
1246 _DrawDay(currRow
, currColumn
, row
, column
, counter
, tmp
, day
, focus
, false);
1248 _DrawDay(currRow
, currColumn
, -1, -1, counter
, tmp
, day
, focus
, false);
1250 tmp
.OffsetBy(tmp
.Width(), 0.0);
1252 frame
.OffsetBy(0.0, frame
.Height());
1258 BCalendarView::_UpdateCurrentDate()
1260 BDate date
= BDate::CurrentDate(B_LOCAL_TIME
);
1262 if (!date
.IsValid())
1264 if (date
== fCurrentDate
)
1267 fCurrentDate
= date
;
1270 fCurrentDayChanged
= true;
1271 Draw(_RectOfDay(fCurrentDay
));
1272 Draw(_RectOfDay(fNewCurrentDay
));
1273 fCurrentDayChanged
= false;
1280 BCalendarView::_FirstCalendarItemFrame() const
1285 if (!fDayNameHeaderVisible
)
1288 if (!fWeekNumberHeaderVisible
)
1291 BRect frame
= Bounds();
1292 frame
.right
= frame
.Width() / columns
- 1.0;
1293 frame
.bottom
= frame
.Height() / rows
- 1.0;
1295 float offsetY
= 4.0;
1296 if (fDayNameHeaderVisible
)
1297 offsetY
+= frame
.Height();
1299 float offsetX
= 4.0;
1300 if (fWeekNumberHeaderVisible
)
1301 offsetX
+= frame
.Width();
1303 return frame
.OffsetBySelf(offsetX
, offsetY
);
1308 BCalendarView::_SetNewSelectedDay(const BPoint
& where
)
1310 BRect frame
= _FirstCalendarItemFrame();
1313 for (int32 row
= 0; row
< 6; ++row
) {
1315 for (int32 column
= 0; column
< 7; ++column
) {
1317 if (tmp
.Contains(where
)) {
1318 fNewSelectedDay
.SetTo(row
, column
);
1321 _GetYearMonthForSelection(fNewSelectedDay
, &year
, &month
);
1322 if (month
== fDate
.Month()) {
1323 // only change date if a day in the current month has been
1325 int32 day
= atoi(fDayNumbers
[row
][column
].String());
1326 fDate
.SetDate(year
, month
, day
);
1330 tmp
.OffsetBy(tmp
.Width(), 0.0);
1332 frame
.OffsetBy(0.0, frame
.Height());
1340 BCalendarView::_RectOfDay(const Selection
& selection
) const
1342 BRect frame
= _FirstCalendarItemFrame();
1345 for (int32 row
= 0; row
< 6; ++row
) {
1347 for (int32 column
= 0; column
< 7; ++column
) {
1349 if (selection
.row
== row
&& selection
.column
== column
)
1351 tmp
.OffsetBy(tmp
.Width(), 0.0);
1353 frame
.OffsetBy(0.0, frame
.Height());
1360 } // namespace BPrivate