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