1e4289a54SKarsten Heimrich /* 2323ba9b7SRyan Leavengood * Copyright 2004-2011, 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> 10323ba9b7SRyan Leavengood * Hamish Morrison <hamish@lavabit.com> 11e4289a54SKarsten Heimrich */ 12e4289a54SKarsten Heimrich 13e4289a54SKarsten Heimrich #include "DateTimeView.h" 14e4289a54SKarsten Heimrich 15323ba9b7SRyan Leavengood #include <time.h> 16323ba9b7SRyan Leavengood #include <syscalls.h> 17323ba9b7SRyan Leavengood 18323ba9b7SRyan Leavengood #include <Box.h> 1978092ae7SKarsten Heimrich #include <CalendarView.h> 209717d515SJoachim Seemer #include <Catalog.h> 21e4289a54SKarsten Heimrich #include <CheckBox.h> 22365839fbSRyan Leavengood #include <ControlLook.h> 2378092ae7SKarsten Heimrich #include <DateTime.h> 24e4289a54SKarsten Heimrich #include <Entry.h> 25e4289a54SKarsten Heimrich #include <File.h> 26e4289a54SKarsten Heimrich #include <FindDirectory.h> 27e4289a54SKarsten Heimrich #include <Message.h> 28e4289a54SKarsten Heimrich #include <Path.h> 29e4289a54SKarsten Heimrich #include <StringView.h> 30e4289a54SKarsten Heimrich #include <Window.h> 3138ac8defSOliver Tappe 32323ba9b7SRyan Leavengood #include "AnalogClock.h" 33323ba9b7SRyan Leavengood #include "DateTimeEdit.h" 34323ba9b7SRyan Leavengood #include "TimeMessages.h" 35323ba9b7SRyan Leavengood #include "TimeWindow.h" 36e4289a54SKarsten Heimrich 3738ac8defSOliver Tappe 389717d515SJoachim Seemer #undef B_TRANSLATE_CONTEXT 399717d515SJoachim Seemer #define B_TRANSLATE_CONTEXT "Time" 409717d515SJoachim Seemer 41e4289a54SKarsten Heimrich 4278092ae7SKarsten Heimrich using BPrivate::BCalendarView; 4378092ae7SKarsten Heimrich using BPrivate::BDateTime; 4478092ae7SKarsten Heimrich using BPrivate::B_LOCAL_TIME; 4578092ae7SKarsten Heimrich 4678092ae7SKarsten Heimrich 47323ba9b7SRyan Leavengood DateTimeView::DateTimeView(const char* name) 48323ba9b7SRyan Leavengood : 49323ba9b7SRyan Leavengood BGroupView(name, B_HORIZONTAL, 5), 501cae077aSStephan Aßmus fInitialized(false), 511cae077aSStephan Aßmus fSystemTimeAtStart(system_time()) 52e4289a54SKarsten Heimrich { 5385b69a94SKarsten Heimrich _InitView(); 541cae077aSStephan Aßmus 551cae077aSStephan Aßmus // record the current time to enable revert. 561cae077aSStephan Aßmus time(&fTimeAtStart); 57e4289a54SKarsten Heimrich } 58e4289a54SKarsten Heimrich 59e4289a54SKarsten Heimrich 60e4289a54SKarsten Heimrich DateTimeView::~DateTimeView() 61e4289a54SKarsten Heimrich { 62e4289a54SKarsten Heimrich } 63e4289a54SKarsten Heimrich 64e4289a54SKarsten Heimrich 65e4289a54SKarsten Heimrich void 66e4289a54SKarsten Heimrich DateTimeView::AttachedToWindow() 67e4289a54SKarsten Heimrich { 68e4289a54SKarsten Heimrich if (Parent()) 69e4289a54SKarsten Heimrich SetViewColor(Parent()->ViewColor()); 70e4289a54SKarsten Heimrich 71e4289a54SKarsten Heimrich if (!fInitialized) { 72e4289a54SKarsten Heimrich fInitialized = true; 7385b69a94SKarsten Heimrich 7485b69a94SKarsten Heimrich fCalendarView->SetTarget(this); 75e4289a54SKarsten Heimrich } 76f64b502dSRyan Leavengood 77f64b502dSRyan Leavengood _NotifyClockSettingChanged(); 78e4289a54SKarsten Heimrich } 79e4289a54SKarsten Heimrich 80e4289a54SKarsten Heimrich 81e4289a54SKarsten Heimrich void 82e4289a54SKarsten Heimrich DateTimeView::MessageReceived(BMessage* message) 83e4289a54SKarsten Heimrich { 84e4289a54SKarsten Heimrich int32 change; 85e4289a54SKarsten Heimrich switch (message->what) { 86e4289a54SKarsten Heimrich case B_OBSERVER_NOTICE_CHANGE: 87e4289a54SKarsten Heimrich message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change); 88e4289a54SKarsten Heimrich switch (change) { 89e4289a54SKarsten Heimrich case H_TM_CHANGED: 90e4289a54SKarsten Heimrich _UpdateDateTime(message); 91e4289a54SKarsten Heimrich break; 92e4289a54SKarsten Heimrich 93e4289a54SKarsten Heimrich default: 94e4289a54SKarsten Heimrich BView::MessageReceived(message); 95e4289a54SKarsten Heimrich break; 96e4289a54SKarsten Heimrich } 97e4289a54SKarsten Heimrich break; 98e4289a54SKarsten Heimrich 99e4289a54SKarsten Heimrich case kDayChanged: 100e4289a54SKarsten Heimrich { 101e4289a54SKarsten Heimrich BMessage msg(*message); 102e4289a54SKarsten Heimrich msg.what = H_USER_CHANGE; 103e4289a54SKarsten Heimrich msg.AddBool("time", false); 104e4289a54SKarsten Heimrich Window()->PostMessage(&msg); 1051cae077aSStephan Aßmus break; 1061cae077aSStephan Aßmus } 107e4289a54SKarsten Heimrich 1081cae077aSStephan Aßmus case kMsgRevert: 1091cae077aSStephan Aßmus _Revert(); 110e4289a54SKarsten Heimrich break; 111e4289a54SKarsten Heimrich 1123e58fe9eSStephan Aßmus case kChangeTimeFinished: 1133e58fe9eSStephan Aßmus if (fClock->IsChangingTime()) 1143e58fe9eSStephan Aßmus fTimeEdit->MakeFocus(false); 1153e58fe9eSStephan Aßmus fClock->ChangeTimeFinished(); 1163e58fe9eSStephan Aßmus break; 117d3bde5deSAxel Dörfler 118*c2f3ee3bSAdrien Destugues case kRTCUpdate: 119*c2f3ee3bSAdrien Destugues break; 120*c2f3ee3bSAdrien Destugues 121e4289a54SKarsten Heimrich default: 122e4289a54SKarsten Heimrich BView::MessageReceived(message); 123e4289a54SKarsten Heimrich break; 124e4289a54SKarsten Heimrich } 125e4289a54SKarsten Heimrich } 126e4289a54SKarsten Heimrich 127e4289a54SKarsten Heimrich 128310930fdSStephan Aßmus bool 1291cae077aSStephan Aßmus DateTimeView::CheckCanRevert() 1301cae077aSStephan Aßmus { 1311cae077aSStephan Aßmus // check for changed time 1321cae077aSStephan Aßmus time_t unchangedNow = fTimeAtStart + _PrefletUptime(); 1331cae077aSStephan Aßmus time_t changedNow; 1341cae077aSStephan Aßmus time(&changedNow); 1351cae077aSStephan Aßmus 136*c2f3ee3bSAdrien Destugues return changedNow != unchangedNow; 1371cae077aSStephan Aßmus } 1381cae077aSStephan Aßmus 1391cae077aSStephan Aßmus 1401cae077aSStephan Aßmus void 1411cae077aSStephan Aßmus DateTimeView::_Revert() 1421cae077aSStephan Aßmus { 1431cae077aSStephan Aßmus // Set the clock and calendar as they were at launch time + 144d3bde5deSAxel Dörfler // time elapsed since application launch. 1451cae077aSStephan Aßmus 1461cae077aSStephan Aßmus time_t timeNow = fTimeAtStart + _PrefletUptime(); 1471cae077aSStephan Aßmus struct tm result; 1481cae077aSStephan Aßmus struct tm* timeInfo; 1491cae077aSStephan Aßmus timeInfo = localtime_r(&timeNow, &result); 1501cae077aSStephan Aßmus 1511cae077aSStephan Aßmus BDateTime dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); 1521cae077aSStephan Aßmus BTime time = dateTime.Time(); 1531cae077aSStephan Aßmus BDate date = dateTime.Date(); 1541cae077aSStephan Aßmus time.SetTime(timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec % 60); 1551cae077aSStephan Aßmus date.SetDate(timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, 1561cae077aSStephan Aßmus timeInfo->tm_mday); 1571cae077aSStephan Aßmus dateTime.SetTime(time); 1581cae077aSStephan Aßmus dateTime.SetDate(date); 1591cae077aSStephan Aßmus 1601cae077aSStephan Aßmus set_real_time_clock(dateTime.Time_t()); 1611cae077aSStephan Aßmus } 1621cae077aSStephan Aßmus 1631cae077aSStephan Aßmus 1641cae077aSStephan Aßmus time_t 1651cae077aSStephan Aßmus DateTimeView::_PrefletUptime() const 1661cae077aSStephan Aßmus { 1671cae077aSStephan Aßmus return (time_t)((system_time() - fSystemTimeAtStart) / 1000000); 1681cae077aSStephan Aßmus } 1691cae077aSStephan Aßmus 1701cae077aSStephan Aßmus 1711cae077aSStephan Aßmus void 172e4289a54SKarsten Heimrich DateTimeView::_InitView() 173e4289a54SKarsten Heimrich { 1746846765fSOliver Tappe fCalendarView = new BCalendarView("calendar"); 175e4289a54SKarsten Heimrich fCalendarView->SetWeekNumberHeaderVisible(false); 176e4289a54SKarsten Heimrich fCalendarView->SetSelectionMessage(new BMessage(kDayChanged)); 177e4289a54SKarsten Heimrich fCalendarView->SetInvocationMessage(new BMessage(kDayChanged)); 178e4289a54SKarsten Heimrich 179323ba9b7SRyan Leavengood fDateEdit = new TDateEdit("dateEdit", 3); 180323ba9b7SRyan Leavengood fTimeEdit = new TTimeEdit("timeEdit", 4); 181323ba9b7SRyan Leavengood fClock = new TAnalogClock("analogClock"); 182e4289a54SKarsten Heimrich 18378092ae7SKarsten Heimrich BTime time(BTime::CurrentTime(B_LOCAL_TIME)); 18478092ae7SKarsten Heimrich fClock->SetTime(time.Hour(), time.Minute(), time.Second()); 185e4289a54SKarsten Heimrich 186323ba9b7SRyan Leavengood BBox* divider = new BBox(BRect(0, 0, 1, 1), 187323ba9b7SRyan Leavengood B_EMPTY_STRING, B_FOLLOW_ALL_SIDES, 188323ba9b7SRyan Leavengood B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER); 189323ba9b7SRyan Leavengood divider->SetExplicitMaxSize(BSize(1, B_SIZE_UNLIMITED)); 190323ba9b7SRyan Leavengood 191365839fbSRyan Leavengood const float kInset = be_control_look->DefaultItemSpacing(); 192323ba9b7SRyan Leavengood BLayoutBuilder::Group<>(this) 193365839fbSRyan Leavengood .AddGroup(B_VERTICAL, kInset / 2) 194323ba9b7SRyan Leavengood .Add(fDateEdit) 195323ba9b7SRyan Leavengood .Add(fCalendarView) 196323ba9b7SRyan Leavengood .End() 197323ba9b7SRyan Leavengood .Add(divider) 198365839fbSRyan Leavengood .AddGroup(B_VERTICAL, 0) 199323ba9b7SRyan Leavengood .Add(fTimeEdit) 200323ba9b7SRyan Leavengood .Add(fClock) 201323ba9b7SRyan Leavengood .End() 202365839fbSRyan Leavengood .SetInsets(kInset, kInset, kInset, kInset); 203e4289a54SKarsten Heimrich } 204e4289a54SKarsten Heimrich 205e4289a54SKarsten Heimrich 206e4289a54SKarsten Heimrich void 207e4289a54SKarsten Heimrich DateTimeView::_UpdateDateTime(BMessage* message) 208e4289a54SKarsten Heimrich { 209e4289a54SKarsten Heimrich int32 day; 210e4289a54SKarsten Heimrich int32 month; 211e4289a54SKarsten Heimrich int32 year; 212e4289a54SKarsten Heimrich if (message->FindInt32("month", &month) == B_OK 213e4289a54SKarsten Heimrich && message->FindInt32("day", &day) == B_OK 214d3bde5deSAxel Dörfler && message->FindInt32("year", &year) == B_OK) { 2156846765fSOliver Tappe static int32 lastDay; 2166846765fSOliver Tappe static int32 lastMonth; 2176846765fSOliver Tappe static int32 lastYear; 2186846765fSOliver Tappe if (day != lastDay || month != lastMonth || year != lastYear) { 219e4289a54SKarsten Heimrich fDateEdit->SetDate(year, month, day); 220e4289a54SKarsten Heimrich fCalendarView->SetDate(year, month, day); 2216846765fSOliver Tappe lastDay = day; 2226846765fSOliver Tappe lastMonth = month; 2236846765fSOliver Tappe lastYear = year; 2246846765fSOliver Tappe } 225e4289a54SKarsten Heimrich } 226e4289a54SKarsten Heimrich 227e4289a54SKarsten Heimrich int32 hour; 228e4289a54SKarsten Heimrich int32 minute; 229e4289a54SKarsten Heimrich int32 second; 230e4289a54SKarsten Heimrich if (message->FindInt32("hour", &hour) == B_OK 231e4289a54SKarsten Heimrich && message->FindInt32("minute", &minute) == B_OK 232d3bde5deSAxel Dörfler && message->FindInt32("second", &second) == B_OK) { 233e4289a54SKarsten Heimrich fClock->SetTime(hour, minute, second); 23485b69a94SKarsten Heimrich fTimeEdit->SetTime(hour, minute, second); 235e4289a54SKarsten Heimrich } 236e4289a54SKarsten Heimrich } 237f64b502dSRyan Leavengood 238f64b502dSRyan Leavengood 239f64b502dSRyan Leavengood void 240f64b502dSRyan Leavengood DateTimeView::_NotifyClockSettingChanged() 241f64b502dSRyan Leavengood { 242f64b502dSRyan Leavengood BMessage msg(kMsgClockSettingChanged); 243f64b502dSRyan Leavengood Window()->PostMessage(&msg); 244f64b502dSRyan Leavengood } 245f64b502dSRyan Leavengood 246