xref: /haiku/src/apps/deskbar/CalendarMenuWindow.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
1 /*
2  * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #include "CalendarMenuWindow.h"
6 
7 
8 #include <Button.h>
9 #include <CalendarView.h>
10 #include <GridLayoutBuilder.h>
11 #include <GroupLayout.h>
12 #include <GroupLayoutBuilder.h>
13 #include <GroupView.h>
14 #include <Screen.h>
15 #include <String.h>
16 #include <StringView.h>
17 #include <SpaceLayoutItem.h>
18 
19 
20 using BPrivate::BCalendarView;
21 using BPrivate::B_LOCAL_TIME;
22 using BPrivate::B_WEEK_START_SUNDAY;
23 using BPrivate::B_WEEK_START_MONDAY;
24 
25 
26 // #pragma mark -- FlatButton
27 
28 
29 class FlatButton : public BButton {
30 public:
31 					FlatButton(const BString& label, uint32 what)
32 						: BButton(label.String(), new BMessage(what)) {}
33 	virtual			~FlatButton() {}
34 
35 	virtual void	Draw(BRect updateRect);
36 };
37 
38 
39 void
40 FlatButton::Draw(BRect updateRect)
41 {
42 	updateRect = Bounds();
43 	rgb_color highColor = HighColor();
44 
45 	SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
46 	FillRect(updateRect);
47 
48 	font_height fh;
49 	GetFontHeight(&fh);
50 
51 	const char* label = Label();
52 	const float stringWidth = StringWidth(label);
53 	const float x = (updateRect.right - stringWidth) / 2.0f;
54 	const float labelY = updateRect.top
55 		+ ((updateRect.Height() - fh.ascent - fh.descent) / 2.0f)
56 		+ fh.ascent + 1.0f;
57 
58 	SetHighColor(highColor);
59 	DrawString(label, BPoint(x, labelY));
60 
61 	if (IsFocus()) {
62 		SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
63 		StrokeRect(updateRect);
64 	}
65 }
66 
67 
68 // #pragma mark -- CalendarMenuWindow
69 
70 
71 enum {
72 	kInvokationMessage,
73 	kMonthDownMessage,
74 	kMonthUpMessage,
75 	kYearDownMessage,
76 	kYearUpMessage
77 };
78 
79 
80 CalendarMenuWindow::CalendarMenuWindow(BPoint where, bool euroDate)
81 	: BWindow(BRect(0.0, 0.0, 100.0, 130.0), "", B_BORDERED_WINDOW,
82 		B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_CLOSE_ON_ESCAPE |
83 		B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE),
84 	  fYearLabel(NULL),
85 	  fMonthLabel(NULL),
86 	  fCalendarView(NULL),
87 	  fSuppressFirstClose(true)
88 {
89 	RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
90 	AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
91 
92 	fYearLabel = new BStringView("year", "");
93 	fYearLabel->SetFontSize(10.0);
94 
95 	fMonthLabel = new BStringView("month", "");
96 	fMonthLabel->SetFontSize(10.0);
97 
98 	fCalendarView = new BCalendarView(Bounds(), "calendar",
99 		euroDate ? B_WEEK_START_MONDAY : B_WEEK_START_SUNDAY, B_FOLLOW_ALL);
100 	fCalendarView->SetInvocationMessage(new BMessage(kInvokationMessage));
101 	fCalendarView->SetFontSize(10.0);
102 
103 	BGroupLayout *layout = new BGroupLayout(B_HORIZONTAL);
104 	SetLayout(layout);
105 
106 	float width, height;
107 	fMonthLabel->GetPreferredSize(&width, &height);
108 
109 	BGridLayout* gridLayout = BGridLayoutBuilder(5.0)
110 		.Add(_SetupButton("-", kMonthDownMessage, height), 0, 0)
111 		.Add(fMonthLabel, 1, 0)
112 		.Add(_SetupButton("+", kMonthUpMessage, height), 2, 0)
113 		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
114 		.Add(_SetupButton("-", kYearDownMessage, height), 4, 0)
115 		.Add(fYearLabel, 5, 0)
116 		.Add(_SetupButton("+", kYearUpMessage, height), 6, 0)
117 		.SetInsets(5.0, 0.0, 5.0, 0.0);
118 	gridLayout->SetMinColumnWidth(1, be_plain_font->StringWidth("September"));
119 
120 	BGroupView* groupView = new BGroupView(B_VERTICAL, 10.0);
121 	BView* view = BGroupLayoutBuilder(B_VERTICAL, 5.0)
122 		.Add(gridLayout->View())
123 		.Add(fCalendarView)
124 		.SetInsets(5.0, 5.0, 5.0, 5.0);
125 	groupView->AddChild(view);
126 	AddChild(groupView);
127 
128 	MoveTo(where);
129 	_UpdateUi(BDate::CurrentDate(B_LOCAL_TIME));
130 }
131 
132 
133 CalendarMenuWindow::~CalendarMenuWindow()
134 {
135 }
136 
137 
138 void
139 CalendarMenuWindow::Show()
140 {
141 	BRect screen(BScreen().Frame());
142 
143 	float right = screen.right;
144 	float bottom = screen.bottom;
145 
146 	BRect rightTop(right / 2.0, screen.top, right, bottom / 2.0);
147 	BRect rightBottom(right / 2.0, bottom / 2.0, right + 1.0, bottom + 1.0);
148 	BRect leftBottom(screen.left, bottom / 2.0, right / 2.0, bottom + 1.0);
149 
150 	BPoint where = Frame().LeftTop();
151 	BSize size = GetLayout()->PreferredSize();
152 
153 	if (rightTop.Contains(where)) {
154 		where.x -= size.width;
155 	} else if (leftBottom.Contains(where)) {
156 		where.y -= (size.height + 4.0);
157 	} else if (rightBottom.Contains(where)) {
158 		where.x -= size.width;
159 		where.y -= (size.height + 4.0);
160 	}
161 
162 	MoveTo(where);
163 	fCalendarView->MakeFocus(true);
164 
165 	BWindow::Show();
166 }
167 
168 
169 void
170 CalendarMenuWindow::WindowActivated(bool active)
171 {
172 	if (active)
173 		return;
174 
175 	if (mouse_mode() == 0) {
176 		if (!active)
177 			PostMessage(B_QUIT_REQUESTED);
178 	} else {
179 		if (fSuppressFirstClose && !active) {
180 			fSuppressFirstClose = false; return;
181 		}
182 
183 		if (!fSuppressFirstClose && !active)
184 			PostMessage(B_QUIT_REQUESTED);
185 	}
186 }
187 
188 
189 void
190 CalendarMenuWindow::MessageReceived(BMessage* message)
191 {
192 	switch (message->what) {
193 		case kInvokationMessage: {
194 			int32 day, month, year;
195 			message->FindInt32("day", &day);
196 			message->FindInt32("month", &month);
197 			message->FindInt32("year", &year);
198 
199 			_UpdateUi(BDate(year, month, day));
200 		}	break;
201 
202 		case kMonthDownMessage: {
203 		case kMonthUpMessage:
204 			BDate date = fCalendarView->Date();
205 
206 			int32 day = date.Day();
207 			int32 year = date.Year();
208 			int32 month = date.Month();
209 
210 			month += (kMonthDownMessage == message->what) ? -1 : 1;
211 			if (month < 1) {
212 				year--;
213 				month = 12;
214 			} else if (month > 12) {
215 				year++;
216 				month = 1;
217 			}
218 			date.SetDate(year, month, day);
219 
220 			if (day > date.DaysInMonth())
221 				day = date.DaysInMonth();
222 
223 			_UpdateUi(BDate(year, month, day));
224 		}	break;
225 
226 		case kYearDownMessage: {
227 		case kYearUpMessage:
228 			BDate date = fCalendarView->Date();
229 			int32 i = kYearDownMessage == message->what ? -1 : 1;
230 			_UpdateUi(BDate(date.Year() + i, date.Month(), date.Day()));
231 		}	break;
232 
233 		default: {
234 			BWindow::MessageReceived(message);
235 		}	break;
236 	}
237 }
238 
239 
240 void
241 CalendarMenuWindow::_UpdateUi(const BDate& date)
242 {
243 	if (!date.IsValid())
244 		return;
245 
246 	fCalendarView->SetDate(date);
247 
248 	BString text;
249 	text << date.Year();
250 	fYearLabel->SetText(text.String());
251 
252 	fMonthLabel->SetText(date.LongMonthName(date.Month()).String());
253 }
254 
255 
256 BButton*
257 CalendarMenuWindow::_SetupButton(const char* label, uint32 what, float height)
258 {
259 	FlatButton* button = new FlatButton(label, what);
260 	button->SetExplicitMinSize(BSize(height, height));
261 	button->SetFontSize(10.0);
262 
263 	return button;
264 }
265