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