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