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