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