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 22using BPrivate::BCalendarView; 23 24enum { 25 kInvokationMessage, 26 kMonthDownMessage, 27 kMonthUpMessage, 28 kYearDownMessage, 29 kYearUpMessage 30}; 31 32 33// #pragma mark - FlatButton 34 35 36class FlatButton : public BButton { 37public: 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 46void 47FlatButton::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 78CalendarMenuWindow::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 131CalendarMenuWindow::~CalendarMenuWindow() 132{ 133} 134 135 136void 137CalendarMenuWindow::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 167void 168CalendarMenuWindow::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 188void 189CalendarMenuWindow::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 228void 229CalendarMenuWindow::_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 244BButton* 245CalendarMenuWindow::_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