xref: /haiku/src/apps/deskbar/CalendarMenuWindow.cpp (revision 62f5ba006a08b0df30631375878effaf67ae5dbc)
1 /*
2  * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "CalendarMenuWindow.h"
8 
9 #include <Button.h>
10 #include <CalendarView.h>
11 #include <GridLayoutBuilder.h>
12 #include <GroupLayout.h>
13 #include <GroupLayoutBuilder.h>
14 #include <GroupView.h>
15 #include <Screen.h>
16 #include <SpaceLayoutItem.h>
17 #include <String.h>
18 #include <StringView.h>
19 
20 
21 using BPrivate::BCalendarView;
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 	:
82 	BWindow(BRect(0.0, 0.0, 100.0, 130.0), "", B_BORDERED_WINDOW,
83 		B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_CLOSE_ON_ESCAPE
84 		| B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE),
85 	fYearLabel(NULL),
86 	fMonthLabel(NULL),
87 	fCalendarView(NULL),
88 	fSuppressFirstClose(true)
89 {
90 	RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
91 	AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
92 
93 	fYearLabel = new BStringView("year", "");
94 	fYearLabel->SetFontSize(10.0);
95 
96 	fMonthLabel = new BStringView("month", "");
97 	fMonthLabel->SetFontSize(10.0);
98 
99 	fCalendarView = new BCalendarView(Bounds(), "calendar",
100 		euroDate ? B_WEEK_START_MONDAY : B_WEEK_START_SUNDAY, B_FOLLOW_ALL);
101 	fCalendarView->SetInvocationMessage(new BMessage(kInvokationMessage));
102 	fCalendarView->SetFontSize(10.0);
103 
104 	BGroupLayout* layout = new BGroupLayout(B_HORIZONTAL);
105 	SetLayout(layout);
106 
107 	float width, height;
108 	fMonthLabel->GetPreferredSize(&width, &height);
109 
110 	BGridLayout* gridLayout = BGridLayoutBuilder(5.0)
111 		.Add(_SetupButton("-", kMonthDownMessage, height), 0, 0)
112 		.Add(fMonthLabel, 1, 0)
113 		.Add(_SetupButton("+", kMonthUpMessage, height), 2, 0)
114 		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
115 		.Add(_SetupButton("-", kYearDownMessage, height), 4, 0)
116 		.Add(fYearLabel, 5, 0)
117 		.Add(_SetupButton("+", kYearUpMessage, height), 6, 0)
118 		.SetInsets(5.0, 0.0, 5.0, 0.0);
119 	gridLayout->SetMinColumnWidth(1, be_plain_font->StringWidth("September"));
120 
121 	BGroupView* groupView = new BGroupView(B_VERTICAL, 10.0);
122 	BView* view = BGroupLayoutBuilder(B_VERTICAL, 5.0)
123 		.Add(gridLayout->View())
124 		.Add(fCalendarView)
125 		.SetInsets(5.0, 5.0, 5.0, 5.0);
126 	groupView->AddChild(view);
127 	AddChild(groupView);
128 
129 	MoveTo(where);
130 	_UpdateUI(BDate::CurrentDate(B_LOCAL_TIME));
131 }
132 
133 
134 CalendarMenuWindow::~CalendarMenuWindow()
135 {
136 }
137 
138 
139 void
140 CalendarMenuWindow::Show()
141 {
142 	BRect screen(BScreen().Frame());
143 
144 	float right = screen.right;
145 	float bottom = screen.bottom;
146 
147 	BRect rightTop(right / 2.0, screen.top, right, bottom / 2.0);
148 	BRect rightBottom(right / 2.0, bottom / 2.0, right + 1.0, bottom + 1.0);
149 	BRect leftBottom(screen.left, bottom / 2.0, right / 2.0, bottom + 1.0);
150 
151 	BPoint where = Frame().LeftTop();
152 	BSize size = GetLayout()->PreferredSize();
153 
154 	if (rightTop.Contains(where)) {
155 		where.x -= size.width;
156 	} else if (leftBottom.Contains(where)) {
157 		where.y -= (size.height + 4.0);
158 	} else if (rightBottom.Contains(where)) {
159 		where.x -= size.width;
160 		where.y -= (size.height + 4.0);
161 	}
162 
163 	MoveTo(where);
164 	fCalendarView->MakeFocus(true);
165 
166 	BWindow::Show();
167 }
168 
169 
170 void
171 CalendarMenuWindow::WindowActivated(bool active)
172 {
173 	if (active)
174 		return;
175 
176 	if (mouse_mode() != B_FOCUS_FOLLOWS_MOUSE) {
177 		if (!active)
178 			PostMessage(B_QUIT_REQUESTED);
179 	} else {
180 		if (fSuppressFirstClose && !active) {
181 			fSuppressFirstClose = false;
182 			return;
183 		}
184 
185 		if (!fSuppressFirstClose && !active)
186 			PostMessage(B_QUIT_REQUESTED);
187 	}
188 }
189 
190 
191 void
192 CalendarMenuWindow::MessageReceived(BMessage* message)
193 {
194 	switch (message->what) {
195 		case kInvokationMessage:
196 		{
197 			int32 day, month, year;
198 			message->FindInt32("day", &day);
199 			message->FindInt32("month", &month);
200 			message->FindInt32("year", &year);
201 
202 			_UpdateUI(BDate(year, month, day));
203 			break;
204 		}
205 
206 		case kMonthDownMessage:
207 		case kMonthUpMessage:
208 		{
209 			BDate date = fCalendarView->Date();
210 
211 			int32 day = date.Day();
212 			int32 year = date.Year();
213 			int32 month = date.Month();
214 
215 			month += (kMonthDownMessage == message->what) ? -1 : 1;
216 			if (month < 1) {
217 				year--;
218 				month = 12;
219 			} else if (month > 12) {
220 				year++;
221 				month = 1;
222 			}
223 			date.SetDate(year, month, day);
224 
225 			if (day > date.DaysInMonth())
226 				day = date.DaysInMonth();
227 
228 			_UpdateUI(BDate(year, month, day));
229 			break;
230 		}
231 
232 		case kYearDownMessage:
233 		case kYearUpMessage:
234 		{
235 			BDate date = fCalendarView->Date();
236 			int32 i = kYearDownMessage == message->what ? -1 : 1;
237 			_UpdateUI(BDate(date.Year() + i, date.Month(), date.Day()));
238 			break;
239 		}
240 
241 		default:
242 			BWindow::MessageReceived(message);
243 			break;
244 	}
245 }
246 
247 
248 void
249 CalendarMenuWindow::_UpdateUI(const BDate& date)
250 {
251 	if (!date.IsValid())
252 		return;
253 
254 	fCalendarView->SetDate(date);
255 
256 	BString text;
257 	text << date.Year();
258 	fYearLabel->SetText(text.String());
259 
260 	fMonthLabel->SetText(date.LongMonthName(date.Month()).String());
261 }
262 
263 
264 BButton*
265 CalendarMenuWindow::_SetupButton(const char* label, uint32 what, float height)
266 {
267 	FlatButton* button = new FlatButton(label, what);
268 	button->SetExplicitMinSize(BSize(height, height));
269 	button->SetFontSize(be_plain_font->Size() * 0.8);
270 
271 	return button;
272 }
273 
274