1 /* 2 * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #include "CalendarMenuWindow.h" 6 7 8 #include <Button.h> 9 #include <CalendarView.h> 10 #include <GridLayoutBuilder.h> 11 #include <GroupLayout.h> 12 #include <GroupLayoutBuilder.h> 13 #include <GroupView.h> 14 #include <Screen.h> 15 #include <String.h> 16 #include <StringView.h> 17 #include <SpaceLayoutItem.h> 18 19 20 using BPrivate::BCalendarView; 21 using BPrivate::B_LOCAL_TIME; 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 : BWindow(BRect(0.0, 0.0, 100.0, 130.0), "", B_BORDERED_WINDOW, 82 B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_CLOSE_ON_ESCAPE | 83 B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE), 84 fYearLabel(NULL), 85 fMonthLabel(NULL), 86 fCalendarView(NULL), 87 fSuppressFirstClose(true) 88 { 89 RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY); 90 AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 91 92 fYearLabel = new BStringView("year", ""); 93 fYearLabel->SetFontSize(10.0); 94 95 fMonthLabel = new BStringView("month", ""); 96 fMonthLabel->SetFontSize(10.0); 97 98 fCalendarView = new BCalendarView(Bounds(), "calendar", 99 euroDate ? B_WEEK_START_MONDAY : B_WEEK_START_SUNDAY, B_FOLLOW_ALL); 100 fCalendarView->SetInvocationMessage(new BMessage(kInvokationMessage)); 101 fCalendarView->SetFontSize(10.0); 102 103 BGroupLayout *layout = new BGroupLayout(B_HORIZONTAL); 104 SetLayout(layout); 105 106 float width, height; 107 fMonthLabel->GetPreferredSize(&width, &height); 108 109 BGridLayout* gridLayout = BGridLayoutBuilder(5.0) 110 .Add(_SetupButton("-", kMonthDownMessage, height), 0, 0) 111 .Add(fMonthLabel, 1, 0) 112 .Add(_SetupButton("+", kMonthUpMessage, height), 2, 0) 113 .Add(BSpaceLayoutItem::CreateGlue(), 3, 0) 114 .Add(_SetupButton("-", kYearDownMessage, height), 4, 0) 115 .Add(fYearLabel, 5, 0) 116 .Add(_SetupButton("+", kYearUpMessage, height), 6, 0) 117 .SetInsets(5.0, 0.0, 5.0, 0.0); 118 gridLayout->SetMinColumnWidth(1, be_plain_font->StringWidth("September")); 119 120 BGroupView* groupView = new BGroupView(B_VERTICAL, 10.0); 121 BView* view = BGroupLayoutBuilder(B_VERTICAL, 5.0) 122 .Add(gridLayout->View()) 123 .Add(fCalendarView) 124 .SetInsets(5.0, 5.0, 5.0, 5.0); 125 groupView->AddChild(view); 126 AddChild(groupView); 127 128 MoveTo(where); 129 _UpdateUi(BDate::CurrentDate(B_LOCAL_TIME)); 130 } 131 132 133 CalendarMenuWindow::~CalendarMenuWindow() 134 { 135 } 136 137 138 void 139 CalendarMenuWindow::Show() 140 { 141 BRect screen(BScreen().Frame()); 142 143 float right = screen.right; 144 float bottom = screen.bottom; 145 146 BRect rightTop(right / 2.0, screen.top, right, bottom / 2.0); 147 BRect rightBottom(right / 2.0, bottom / 2.0, right + 1.0, bottom + 1.0); 148 BRect leftBottom(screen.left, bottom / 2.0, right / 2.0, bottom + 1.0); 149 150 BPoint where = Frame().LeftTop(); 151 BSize size = GetLayout()->PreferredSize(); 152 153 if (rightTop.Contains(where)) { 154 where.x -= size.width; 155 } else if (leftBottom.Contains(where)) { 156 where.y -= (size.height + 4.0); 157 } else if (rightBottom.Contains(where)) { 158 where.x -= size.width; 159 where.y -= (size.height + 4.0); 160 } 161 162 MoveTo(where); 163 fCalendarView->MakeFocus(true); 164 165 BWindow::Show(); 166 } 167 168 169 void 170 CalendarMenuWindow::WindowActivated(bool active) 171 { 172 if (active) 173 return; 174 175 if (mouse_mode() == 0) { 176 if (!active) 177 PostMessage(B_QUIT_REQUESTED); 178 } else { 179 if (fSuppressFirstClose && !active) { 180 fSuppressFirstClose = false; return; 181 } 182 183 if (!fSuppressFirstClose && !active) 184 PostMessage(B_QUIT_REQUESTED); 185 } 186 } 187 188 189 void 190 CalendarMenuWindow::MessageReceived(BMessage* message) 191 { 192 switch (message->what) { 193 case kInvokationMessage: { 194 int32 day, month, year; 195 message->FindInt32("day", &day); 196 message->FindInt32("month", &month); 197 message->FindInt32("year", &year); 198 199 _UpdateUi(BDate(year, month, day)); 200 } break; 201 202 case kMonthDownMessage: { 203 case kMonthUpMessage: 204 BDate date = fCalendarView->Date(); 205 206 int32 day = date.Day(); 207 int32 year = date.Year(); 208 int32 month = date.Month(); 209 210 month += (kMonthDownMessage == message->what) ? -1 : 1; 211 if (month < 1) { 212 year--; 213 month = 12; 214 } else if (month > 12) { 215 year++; 216 month = 1; 217 } 218 date.SetDate(year, month, day); 219 220 if (day > date.DaysInMonth()) 221 day = date.DaysInMonth(); 222 223 _UpdateUi(BDate(year, month, day)); 224 } break; 225 226 case kYearDownMessage: { 227 case kYearUpMessage: 228 BDate date = fCalendarView->Date(); 229 int32 i = kYearDownMessage == message->what ? -1 : 1; 230 _UpdateUi(BDate(date.Year() + i, date.Month(), date.Day())); 231 } break; 232 233 default: { 234 BWindow::MessageReceived(message); 235 } break; 236 } 237 } 238 239 240 void 241 CalendarMenuWindow::_UpdateUi(const BDate& date) 242 { 243 if (!date.IsValid()) 244 return; 245 246 fCalendarView->SetDate(date); 247 248 BString text; 249 text << date.Year(); 250 fYearLabel->SetText(text.String()); 251 252 fMonthLabel->SetText(date.LongMonthName(date.Month()).String()); 253 } 254 255 256 BButton* 257 CalendarMenuWindow::_SetupButton(const char* label, uint32 what, float height) 258 { 259 FlatButton* button = new FlatButton(label, what); 260 button->SetExplicitMinSize(BSize(height, height)); 261 button->SetFontSize(10.0); 262 263 return button; 264 } 265