1e4289a54SKarsten Heimrich /* 2e4289a54SKarsten Heimrich * Copyright 2004-2007, Haiku, Inc. All Rights Reserved. 3e4289a54SKarsten Heimrich * Distributed under the terms of the MIT License. 4e4289a54SKarsten Heimrich * 5e4289a54SKarsten Heimrich * Authors: 6e4289a54SKarsten Heimrich * Andrew McCall <mccall@@digitalparadise.co.uk> 7e4289a54SKarsten Heimrich * Mike Berg <mike@berg-net.us> 8e4289a54SKarsten Heimrich * Julun <host.haiku@gmx.de> 91cae077aSStephan Aßmus * Philippe Saint-Pierre <stpere@gmail.com> 10e4289a54SKarsten Heimrich */ 11e4289a54SKarsten Heimrich 12e4289a54SKarsten Heimrich #include "DateTimeView.h" 13e4289a54SKarsten Heimrich #include "AnalogClock.h" 14e4289a54SKarsten Heimrich #include "CalendarView.h" 15e4289a54SKarsten Heimrich #include "DateTimeEdit.h" 16e4289a54SKarsten Heimrich #include "TimeMessages.h" 171cae077aSStephan Aßmus #include "DateTime.h" 18*310930fdSStephan Aßmus #include "TimeWindow.h" 19e4289a54SKarsten Heimrich 20e4289a54SKarsten Heimrich 21e4289a54SKarsten Heimrich #include <CheckBox.h> 22e4289a54SKarsten Heimrich #include <Entry.h> 23e4289a54SKarsten Heimrich #include <File.h> 24e4289a54SKarsten Heimrich #include <FindDirectory.h> 25e4289a54SKarsten Heimrich #include <Message.h> 26e4289a54SKarsten Heimrich #include <Path.h> 27e4289a54SKarsten Heimrich #include <RadioButton.h> 28e4289a54SKarsten Heimrich #include <String.h> 29e4289a54SKarsten Heimrich #include <StringView.h> 30e4289a54SKarsten Heimrich #include <Window.h> 311cae077aSStephan Aßmus #include <time.h> 32e4289a54SKarsten Heimrich 33e4289a54SKarsten Heimrich 34e4289a54SKarsten Heimrich #ifdef HAIKU_TARGET_PLATFORM_HAIKU 35e4289a54SKarsten Heimrich # include <syscalls.h> 36e4289a54SKarsten Heimrich #else 37a22279faSAxel Dörfler extern "C" void _kset_tzfilename_(const char *name, size_t length, bool isGMT); 38e4289a54SKarsten Heimrich # define _kern_set_tzfilename _kset_tzfilename_ 39e4289a54SKarsten Heimrich #endif 40e4289a54SKarsten Heimrich 41e4289a54SKarsten Heimrich 42e4289a54SKarsten Heimrich DateTimeView::DateTimeView(BRect frame) 4385b69a94SKarsten Heimrich : BView(frame, "dateTimeView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP), 44e4289a54SKarsten Heimrich fGmtTime(NULL), 4585b69a94SKarsten Heimrich fUseGmtTime(false), 461cae077aSStephan Aßmus fInitialized(false), 471cae077aSStephan Aßmus fSystemTimeAtStart(system_time()) 48e4289a54SKarsten Heimrich { 49e4289a54SKarsten Heimrich _ReadRTCSettings(); 5085b69a94SKarsten Heimrich _InitView(); 511cae077aSStephan Aßmus 521cae077aSStephan Aßmus // record the current time to enable revert. 531cae077aSStephan Aßmus time(&fTimeAtStart); 54e4289a54SKarsten Heimrich } 55e4289a54SKarsten Heimrich 56e4289a54SKarsten Heimrich 57e4289a54SKarsten Heimrich DateTimeView::~DateTimeView() 58e4289a54SKarsten Heimrich { 59e4289a54SKarsten Heimrich _WriteRTCSettings(); 60e4289a54SKarsten Heimrich } 61e4289a54SKarsten Heimrich 62e4289a54SKarsten Heimrich 63e4289a54SKarsten Heimrich void 64e4289a54SKarsten Heimrich DateTimeView::AttachedToWindow() 65e4289a54SKarsten Heimrich { 66e4289a54SKarsten Heimrich if (Parent()) 67e4289a54SKarsten Heimrich SetViewColor(Parent()->ViewColor()); 68e4289a54SKarsten Heimrich 69e4289a54SKarsten Heimrich if (!fInitialized) { 70e4289a54SKarsten Heimrich fInitialized = true; 7185b69a94SKarsten Heimrich 7285b69a94SKarsten Heimrich fCalendarView->SetTarget(this); 73e4289a54SKarsten Heimrich } 74e4289a54SKarsten Heimrich } 75e4289a54SKarsten Heimrich 76e4289a54SKarsten Heimrich 77e4289a54SKarsten Heimrich void 78e4289a54SKarsten Heimrich DateTimeView::Draw(BRect /*updateRect*/) 79e4289a54SKarsten Heimrich { 80e4289a54SKarsten Heimrich rgb_color viewcolor = ViewColor(); 81e4289a54SKarsten Heimrich rgb_color dark = tint_color(viewcolor, B_DARKEN_4_TINT); 82e4289a54SKarsten Heimrich rgb_color light = tint_color(viewcolor, B_LIGHTEN_MAX_TINT); 83e4289a54SKarsten Heimrich 84e4289a54SKarsten Heimrich //draw a separator line 85e4289a54SKarsten Heimrich BRect bounds(Bounds()); 8685b69a94SKarsten Heimrich BPoint start(bounds.Width() / 2.0f, bounds.top + 5.0f); 8785b69a94SKarsten Heimrich BPoint end(bounds.Width() / 2.0, bounds.bottom - 5.0f); 88e4289a54SKarsten Heimrich 89e4289a54SKarsten Heimrich BeginLineArray(2); 90e4289a54SKarsten Heimrich AddLine(start, end, dark); 91e4289a54SKarsten Heimrich start.x++; 92e4289a54SKarsten Heimrich end.x++; 93e4289a54SKarsten Heimrich AddLine(start, end, light); 94e4289a54SKarsten Heimrich EndLineArray(); 95e4289a54SKarsten Heimrich 96e4289a54SKarsten Heimrich fTimeEdit->Draw(bounds); 97e4289a54SKarsten Heimrich fDateEdit->Draw(bounds); 98e4289a54SKarsten Heimrich } 99e4289a54SKarsten Heimrich 100e4289a54SKarsten Heimrich 101e4289a54SKarsten Heimrich void 102e4289a54SKarsten Heimrich DateTimeView::MessageReceived(BMessage *message) 103e4289a54SKarsten Heimrich { 104e4289a54SKarsten Heimrich int32 change; 105e4289a54SKarsten Heimrich switch(message->what) { 106e4289a54SKarsten Heimrich case B_OBSERVER_NOTICE_CHANGE: 107e4289a54SKarsten Heimrich message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change); 108e4289a54SKarsten Heimrich switch(change) { 109e4289a54SKarsten Heimrich case H_TM_CHANGED: 110e4289a54SKarsten Heimrich _UpdateDateTime(message); 111e4289a54SKarsten Heimrich break; 112e4289a54SKarsten Heimrich 113e4289a54SKarsten Heimrich default: 114e4289a54SKarsten Heimrich BView::MessageReceived(message); 115e4289a54SKarsten Heimrich break; 116e4289a54SKarsten Heimrich } 117e4289a54SKarsten Heimrich break; 118e4289a54SKarsten Heimrich 119e4289a54SKarsten Heimrich case kDayChanged: 120e4289a54SKarsten Heimrich { 121e4289a54SKarsten Heimrich BMessage msg(*message); 122e4289a54SKarsten Heimrich msg.what = H_USER_CHANGE; 123e4289a54SKarsten Heimrich msg.AddBool("time", false); 124e4289a54SKarsten Heimrich Window()->PostMessage(&msg); 1251cae077aSStephan Aßmus break; 1261cae077aSStephan Aßmus } 127e4289a54SKarsten Heimrich 128e4289a54SKarsten Heimrich case kRTCUpdate: 1291cae077aSStephan Aßmus fUseGmtTime = fGmtTime->Value() == B_CONTROL_ON; 130e4289a54SKarsten Heimrich _UpdateGmtSettings(); 1311cae077aSStephan Aßmus break; 1321cae077aSStephan Aßmus 1331cae077aSStephan Aßmus case kMsgRevert: 1341cae077aSStephan Aßmus _Revert(); 135e4289a54SKarsten Heimrich break; 136e4289a54SKarsten Heimrich 137e4289a54SKarsten Heimrich default: 138e4289a54SKarsten Heimrich BView::MessageReceived(message); 139e4289a54SKarsten Heimrich break; 140e4289a54SKarsten Heimrich } 141e4289a54SKarsten Heimrich } 142e4289a54SKarsten Heimrich 143e4289a54SKarsten Heimrich 144*310930fdSStephan Aßmus bool 1451cae077aSStephan Aßmus DateTimeView::CheckCanRevert() 1461cae077aSStephan Aßmus { 1471cae077aSStephan Aßmus // check GMT vs Local setting 1481cae077aSStephan Aßmus bool enable = fUseGmtTime != fOldUseGmtTime; 1491cae077aSStephan Aßmus 1501cae077aSStephan Aßmus // check for changed time 1511cae077aSStephan Aßmus time_t unchangedNow = fTimeAtStart + _PrefletUptime(); 1521cae077aSStephan Aßmus time_t changedNow; 1531cae077aSStephan Aßmus time(&changedNow); 1541cae077aSStephan Aßmus 155*310930fdSStephan Aßmus return enable || (changedNow != unchangedNow); 1561cae077aSStephan Aßmus } 1571cae077aSStephan Aßmus 1581cae077aSStephan Aßmus 1591cae077aSStephan Aßmus void 1601cae077aSStephan Aßmus DateTimeView::_Revert() 1611cae077aSStephan Aßmus { 1621cae077aSStephan Aßmus // Set the clock and calendar as they were at launch time + 1631cae077aSStephan Aßmus // time ellapsed since application launch. 1641cae077aSStephan Aßmus 1651cae077aSStephan Aßmus fUseGmtTime = fOldUseGmtTime; 1661cae077aSStephan Aßmus _UpdateGmtSettings(); 1671cae077aSStephan Aßmus 1681cae077aSStephan Aßmus if (fUseGmtTime) 1691cae077aSStephan Aßmus fGmtTime->SetValue(B_CONTROL_ON); 1701cae077aSStephan Aßmus else 1711cae077aSStephan Aßmus fLocalTime->SetValue(B_CONTROL_ON); 1721cae077aSStephan Aßmus 1731cae077aSStephan Aßmus time_t timeNow = fTimeAtStart + _PrefletUptime(); 1741cae077aSStephan Aßmus struct tm result; 1751cae077aSStephan Aßmus struct tm* timeInfo; 1761cae077aSStephan Aßmus timeInfo = localtime_r(&timeNow, &result); 1771cae077aSStephan Aßmus 1781cae077aSStephan Aßmus BDateTime dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); 1791cae077aSStephan Aßmus BTime time = dateTime.Time(); 1801cae077aSStephan Aßmus BDate date = dateTime.Date(); 1811cae077aSStephan Aßmus time.SetTime(timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec % 60); 1821cae077aSStephan Aßmus date.SetDate(timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, 1831cae077aSStephan Aßmus timeInfo->tm_mday); 1841cae077aSStephan Aßmus dateTime.SetTime(time); 1851cae077aSStephan Aßmus dateTime.SetDate(date); 1861cae077aSStephan Aßmus 1871cae077aSStephan Aßmus set_real_time_clock(dateTime.Time_t()); 1881cae077aSStephan Aßmus } 1891cae077aSStephan Aßmus 1901cae077aSStephan Aßmus 1911cae077aSStephan Aßmus time_t 1921cae077aSStephan Aßmus DateTimeView::_PrefletUptime() const 1931cae077aSStephan Aßmus { 1941cae077aSStephan Aßmus return (time_t)((system_time() - fSystemTimeAtStart) / 1000000); 1951cae077aSStephan Aßmus } 1961cae077aSStephan Aßmus 1971cae077aSStephan Aßmus 1981cae077aSStephan Aßmus void 199e4289a54SKarsten Heimrich DateTimeView::_InitView() 200e4289a54SKarsten Heimrich { 201e4289a54SKarsten Heimrich font_height fontHeight; 202e4289a54SKarsten Heimrich be_plain_font->GetHeight(&fontHeight); 20385b69a94SKarsten Heimrich float textHeight = fontHeight.descent + fontHeight.ascent 20485b69a94SKarsten Heimrich + fontHeight.leading + 6.0; // 6px border 205e4289a54SKarsten Heimrich 206e4289a54SKarsten Heimrich // left side 20785b69a94SKarsten Heimrich BRect bounds = Bounds(); 20885b69a94SKarsten Heimrich bounds.InsetBy(10.0, 10.0); 20985b69a94SKarsten Heimrich bounds.top += textHeight + 10.0; 210e4289a54SKarsten Heimrich 21185b69a94SKarsten Heimrich fCalendarView = new BCalendarView(bounds, "calendar"); 212e4289a54SKarsten Heimrich fCalendarView->SetWeekNumberHeaderVisible(false); 21385b69a94SKarsten Heimrich fCalendarView->ResizeToPreferred(); 214e4289a54SKarsten Heimrich fCalendarView->SetSelectionMessage(new BMessage(kDayChanged)); 215e4289a54SKarsten Heimrich fCalendarView->SetInvocationMessage(new BMessage(kDayChanged)); 216e4289a54SKarsten Heimrich 21785b69a94SKarsten Heimrich bounds.top -= textHeight + 10.0; 21885b69a94SKarsten Heimrich bounds.bottom = bounds.top + textHeight; 21985b69a94SKarsten Heimrich bounds.right = fCalendarView->Frame().right; 220e4289a54SKarsten Heimrich 22185b69a94SKarsten Heimrich fDateEdit = new TDateEdit(bounds, "dateEdit", 3); 22285b69a94SKarsten Heimrich AddChild(fDateEdit); 22385b69a94SKarsten Heimrich AddChild(fCalendarView); 22485b69a94SKarsten Heimrich 22585b69a94SKarsten Heimrich // right side, 2px extra for separator 22685b69a94SKarsten Heimrich bounds.OffsetBy(bounds.Width() + 22.0, 0.0); 22785b69a94SKarsten Heimrich fTimeEdit = new TTimeEdit(bounds, "timeEdit", 4); 228e4289a54SKarsten Heimrich AddChild(fTimeEdit); 229e4289a54SKarsten Heimrich 23085b69a94SKarsten Heimrich bounds = fCalendarView->Frame(); 23185b69a94SKarsten Heimrich bounds.OffsetBy(bounds.Width() + 22.0, 0.0); 232e4289a54SKarsten Heimrich 23385b69a94SKarsten Heimrich fClock = new TAnalogClock(bounds, "analogClock"); 234e4289a54SKarsten Heimrich AddChild(fClock); 235e4289a54SKarsten Heimrich 236e4289a54SKarsten Heimrich // clock radio buttons 23785b69a94SKarsten Heimrich bounds.top = fClock->Frame().bottom + 10.0; 23885b69a94SKarsten Heimrich BStringView *text = new BStringView(bounds, "clockSetTo", "Clock set to:"); 239e4289a54SKarsten Heimrich AddChild(text); 240e4289a54SKarsten Heimrich text->ResizeToPreferred(); 241e4289a54SKarsten Heimrich 24285b69a94SKarsten Heimrich bounds.left += 10.0f; 24385b69a94SKarsten Heimrich bounds.top = text->Frame().bottom; 24485b69a94SKarsten Heimrich fLocalTime = new BRadioButton(bounds, "localTime", "Local Time", 245e4289a54SKarsten Heimrich new BMessage(kRTCUpdate)); 246e4289a54SKarsten Heimrich AddChild(fLocalTime); 247e4289a54SKarsten Heimrich fLocalTime->ResizeToPreferred(); 248e4289a54SKarsten Heimrich 24985b69a94SKarsten Heimrich bounds.left = fLocalTime->Frame().right + 10.0; 25085b69a94SKarsten Heimrich fGmtTime = new BRadioButton(bounds, "greenwichMeanTime", "GMT", 25185b69a94SKarsten Heimrich new BMessage(kRTCUpdate)); 252e4289a54SKarsten Heimrich AddChild(fGmtTime); 253e4289a54SKarsten Heimrich fGmtTime->ResizeToPreferred(); 254e4289a54SKarsten Heimrich 25585b69a94SKarsten Heimrich if (fUseGmtTime) 256e4289a54SKarsten Heimrich fGmtTime->SetValue(B_CONTROL_ON); 25785b69a94SKarsten Heimrich else 25885b69a94SKarsten Heimrich fLocalTime->SetValue(B_CONTROL_ON); 25985b69a94SKarsten Heimrich 2601cae077aSStephan Aßmus fOldUseGmtTime = fUseGmtTime; 2611cae077aSStephan Aßmus 26285b69a94SKarsten Heimrich ResizeTo(fClock->Frame().right + 10.0, fGmtTime->Frame().bottom + 10.0); 263e4289a54SKarsten Heimrich } 264e4289a54SKarsten Heimrich 265e4289a54SKarsten Heimrich 266e4289a54SKarsten Heimrich void 267e4289a54SKarsten Heimrich DateTimeView::_ReadRTCSettings() 268e4289a54SKarsten Heimrich { 269e4289a54SKarsten Heimrich BPath path; 270e4289a54SKarsten Heimrich if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 271e4289a54SKarsten Heimrich return; 272e4289a54SKarsten Heimrich 273e4289a54SKarsten Heimrich path.Append("RTC_time_settings"); 274e4289a54SKarsten Heimrich 275e4289a54SKarsten Heimrich BEntry entry(path.Path()); 276e4289a54SKarsten Heimrich if (entry.Exists()) { 27785b69a94SKarsten Heimrich BFile file(&entry, B_READ_ONLY); 278e4289a54SKarsten Heimrich if (file.InitCheck() == B_OK) { 27985b69a94SKarsten Heimrich char buffer[6]; 28085b69a94SKarsten Heimrich file.Read(buffer, 6); 28185b69a94SKarsten Heimrich if (strncmp(buffer, "gmt", 3) == 0) 28285b69a94SKarsten Heimrich fUseGmtTime = true; 283e4289a54SKarsten Heimrich } 28485b69a94SKarsten Heimrich } else 28585b69a94SKarsten Heimrich _UpdateGmtSettings(); 286e4289a54SKarsten Heimrich } 287e4289a54SKarsten Heimrich 288e4289a54SKarsten Heimrich 289e4289a54SKarsten Heimrich void 290e4289a54SKarsten Heimrich DateTimeView::_WriteRTCSettings() 291e4289a54SKarsten Heimrich { 292e4289a54SKarsten Heimrich BPath path; 293e4289a54SKarsten Heimrich if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 294e4289a54SKarsten Heimrich return; 295e4289a54SKarsten Heimrich 296e4289a54SKarsten Heimrich path.Append("RTC_time_settings"); 297e4289a54SKarsten Heimrich 298e4289a54SKarsten Heimrich BFile file(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); 299e4289a54SKarsten Heimrich if (file.InitCheck() == B_OK) { 30085b69a94SKarsten Heimrich if (fUseGmtTime) 301e4289a54SKarsten Heimrich file.Write("gmt", 3); 30285b69a94SKarsten Heimrich else 30385b69a94SKarsten Heimrich file.Write("local", 5); 304e4289a54SKarsten Heimrich } 305e4289a54SKarsten Heimrich } 306e4289a54SKarsten Heimrich 307e4289a54SKarsten Heimrich 308e4289a54SKarsten Heimrich void 309e4289a54SKarsten Heimrich DateTimeView::_UpdateGmtSettings() 310e4289a54SKarsten Heimrich { 311e4289a54SKarsten Heimrich _WriteRTCSettings(); 312e4289a54SKarsten Heimrich 313e4289a54SKarsten Heimrich BPath path; 314e4289a54SKarsten Heimrich if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 315e4289a54SKarsten Heimrich return; 316e4289a54SKarsten Heimrich 317e4289a54SKarsten Heimrich path.Append("timezone"); 318e4289a54SKarsten Heimrich BEntry entry(path.Path(), true); 319e4289a54SKarsten Heimrich 320e4289a54SKarsten Heimrich if (!entry.Exists()) 321e4289a54SKarsten Heimrich return; 322e4289a54SKarsten Heimrich 323e4289a54SKarsten Heimrich entry.GetPath(&path); 324e4289a54SKarsten Heimrich 325e4289a54SKarsten Heimrich // take the existing timezone and set it's gmt use 32685b69a94SKarsten Heimrich _kern_set_tzfilename(path.Path(), B_PATH_NAME_LENGTH, fUseGmtTime); 327e4289a54SKarsten Heimrich } 328e4289a54SKarsten Heimrich 329e4289a54SKarsten Heimrich 330e4289a54SKarsten Heimrich void 331e4289a54SKarsten Heimrich DateTimeView::_UpdateDateTime(BMessage *message) 332e4289a54SKarsten Heimrich { 333e4289a54SKarsten Heimrich int32 day; 334e4289a54SKarsten Heimrich int32 month; 335e4289a54SKarsten Heimrich int32 year; 336e4289a54SKarsten Heimrich if (message->FindInt32("month", &month) == B_OK 337e4289a54SKarsten Heimrich && message->FindInt32("day", &day) == B_OK 338e4289a54SKarsten Heimrich && message->FindInt32("year", &year) == B_OK) 339e4289a54SKarsten Heimrich { 340e4289a54SKarsten Heimrich fDateEdit->SetDate(year, month, day); 341e4289a54SKarsten Heimrich fCalendarView->SetDate(year, month, day); 342e4289a54SKarsten Heimrich } 343e4289a54SKarsten Heimrich 344e4289a54SKarsten Heimrich int32 hour; 345e4289a54SKarsten Heimrich int32 minute; 346e4289a54SKarsten Heimrich int32 second; 347e4289a54SKarsten Heimrich if (message->FindInt32("hour", &hour) == B_OK 348e4289a54SKarsten Heimrich && message->FindInt32("minute", &minute) == B_OK 349e4289a54SKarsten Heimrich && message->FindInt32("second", &second) == B_OK) 350e4289a54SKarsten Heimrich { 351e4289a54SKarsten Heimrich fClock->SetTime(hour, minute, second); 35285b69a94SKarsten Heimrich fTimeEdit->SetTime(hour, minute, second); 353e4289a54SKarsten Heimrich } 354e4289a54SKarsten Heimrich } 355