xref: /haiku/src/apps/deskbar/CalendarMenuWindow.cpp (revision 1026b0a1a76dc88927bb8175c470f638dc5464ee)
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_ZOOMABLE),
83 	fYearLabel(NULL),
84 	fMonthLabel(NULL),
85 	fCalendarView(NULL),
86 	fSuppressFirstClose(true)
87 {
88 	SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
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 	fMonthLabel = new BStringView("month", "");
95 
96 	fCalendarView = new BCalendarView(Bounds(), "calendar", B_FOLLOW_ALL);
97 	fCalendarView->SetInvocationMessage(new BMessage(kInvokationMessage));
98 
99 	BGroupLayout* layout = new BGroupLayout(B_HORIZONTAL);
100 	SetLayout(layout);
101 
102 	float width, height;
103 	fMonthLabel->GetPreferredSize(&width, &height);
104 
105 	BGridLayout* gridLayout = BGridLayoutBuilder(5.0)
106 		.Add(_SetupButton("-", kMonthDownMessage, height), 0, 0)
107 		.Add(fMonthLabel, 1, 0)
108 		.Add(_SetupButton("+", kMonthUpMessage, height), 2, 0)
109 		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
110 		.Add(_SetupButton("-", kYearDownMessage, height), 4, 0)
111 		.Add(fYearLabel, 5, 0)
112 		.Add(_SetupButton("+", kYearUpMessage, height), 6, 0)
113 		.SetInsets(5.0, 0.0, 5.0, 0.0);
114 	gridLayout->SetMinColumnWidth(1, be_plain_font->StringWidth("September"));
115 
116 	BGroupView* groupView = new BGroupView(B_VERTICAL, 10.0);
117 	BView* view = BGroupLayoutBuilder(B_VERTICAL, 5.0)
118 		.Add(gridLayout->View())
119 		.Add(fCalendarView)
120 		.SetInsets(5.0, 5.0, 5.0, 5.0)
121 		.TopView();
122 	groupView->AddChild(view);
123 	AddChild(groupView);
124 
125 	MoveTo(where);
126 	_UpdateDate(BDate::CurrentDate(B_LOCAL_TIME));
127 }
128 
129 
130 CalendarMenuWindow::~CalendarMenuWindow()
131 {
132 }
133 
134 
135 void
136 CalendarMenuWindow::Show()
137 {
138 	BRect screen(BScreen().Frame());
139 
140 	float right = screen.right;
141 	float bottom = screen.bottom;
142 
143 	BRect rightTop(right / 2.0, screen.top, right, bottom / 2.0);
144 	BRect rightBottom(right / 2.0, bottom / 2.0, right + 1.0, bottom + 1.0);
145 	BRect leftBottom(screen.left, bottom / 2.0, right / 2.0, bottom + 1.0);
146 
147 	BPoint where = Frame().LeftTop();
148 	BSize size = GetLayout()->PreferredSize();
149 
150 	if (rightTop.Contains(where)) {
151 		where.x -= size.width;
152 	} else if (leftBottom.Contains(where)) {
153 		where.y -= (size.height + 4.0);
154 	} else if (rightBottom.Contains(where)) {
155 		where.x -= size.width;
156 		where.y -= (size.height + 4.0);
157 	}
158 
159 	MoveTo(where);
160 	fCalendarView->MakeFocus(true);
161 
162 	BWindow::Show();
163 }
164 
165 
166 void
167 CalendarMenuWindow::WindowActivated(bool active)
168 {
169 	if (active)
170 		return;
171 
172 	if (mouse_mode() != B_FOCUS_FOLLOWS_MOUSE) {
173 		if (!active)
174 			PostMessage(B_QUIT_REQUESTED);
175 	} else {
176 		if (fSuppressFirstClose && !active) {
177 			fSuppressFirstClose = false;
178 			return;
179 		}
180 
181 		if (!fSuppressFirstClose && !active)
182 			PostMessage(B_QUIT_REQUESTED);
183 	}
184 }
185 
186 
187 void
188 CalendarMenuWindow::MessageReceived(BMessage* message)
189 {
190 	switch (message->what) {
191 		case kInvokationMessage:
192 		{
193 			int32 day, month, year;
194 			message->FindInt32("day", &day);
195 			message->FindInt32("month", &month);
196 			message->FindInt32("year", &year);
197 
198 			_UpdateDate(BDate(year, month, day));
199 			break;
200 		}
201 
202 		case kMonthDownMessage:
203 		case kMonthUpMessage:
204 		{
205 			BDate date = fCalendarView->Date();
206 			date.AddMonths(kMonthDownMessage == message->what ? -1 : 1);
207 			_UpdateDate(date);
208 			break;
209 		}
210 
211 		case kYearDownMessage:
212 		case kYearUpMessage:
213 		{
214 			BDate date = fCalendarView->Date();
215 			date.AddYears(kYearDownMessage == message->what ? -1 : 1);
216 			_UpdateDate(date);
217 			break;
218 		}
219 
220 		default:
221 			BWindow::MessageReceived(message);
222 			break;
223 	}
224 }
225 
226 
227 void
228 CalendarMenuWindow::_UpdateDate(const BDate& date)
229 {
230 	if (!date.IsValid())
231 		return;
232 
233 	fCalendarView->SetDate(date);
234 
235 	BString text;
236 	text << date.Year();
237 	fYearLabel->SetText(text.String());
238 
239 	fMonthLabel->SetText(date.LongMonthName(date.Month()).String());
240 }
241 
242 
243 BButton*
244 CalendarMenuWindow::_SetupButton(const char* label, uint32 what, float height)
245 {
246 	FlatButton* button = new FlatButton(label, what);
247 	button->SetExplicitMinSize(BSize(height, height));
248 
249 	return button;
250 }
251