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:
FlatButton(const BString & label,uint32 what)38 FlatButton(const BString& label, uint32 what)
39 : BButton(label.String(), new BMessage(what)) {}
~FlatButton()40 virtual ~FlatButton() {}
41
42 virtual void Draw(BRect updateRect);
43 };
44
45
46 void
Draw(BRect updateRect)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
CalendarMenuWindow(BPoint where)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
~CalendarMenuWindow()131 CalendarMenuWindow::~CalendarMenuWindow()
132 {
133 }
134
135
136 void
Show()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
WindowActivated(bool active)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
MessageReceived(BMessage * message)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
_UpdateDate(const BDate & date)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*
_SetupButton(const char * label,uint32 what,float height)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