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