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