xref: /haiku/src/preferences/time/DateTimeView.cpp (revision 97f11716bfaa0f385eb0e28a52bf56a5023b9e99)
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>
24*cc9bc8c6SJaidyn Ann #include <DateTimeEdit.h>
25e4289a54SKarsten Heimrich #include <Entry.h>
26e4289a54SKarsten Heimrich #include <File.h>
27e4289a54SKarsten Heimrich #include <FindDirectory.h>
289dc78758SAkshay Agarwal #include <LocaleRoster.h>
29e4289a54SKarsten Heimrich #include <Message.h>
30e4289a54SKarsten Heimrich #include <Path.h>
31e4289a54SKarsten Heimrich #include <StringView.h>
32e4289a54SKarsten Heimrich #include <Window.h>
3338ac8defSOliver Tappe 
34323ba9b7SRyan Leavengood #include "AnalogClock.h"
35323ba9b7SRyan Leavengood #include "TimeMessages.h"
36323ba9b7SRyan Leavengood #include "TimeWindow.h"
37e4289a54SKarsten Heimrich 
3838ac8defSOliver Tappe 
39546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
40546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Time"
419717d515SJoachim Seemer 
42e4289a54SKarsten Heimrich 
4378092ae7SKarsten Heimrich using BPrivate::BCalendarView;
4478092ae7SKarsten Heimrich using BPrivate::BDateTime;
4578092ae7SKarsten Heimrich using BPrivate::B_LOCAL_TIME;
46*cc9bc8c6SJaidyn Ann using BPrivate::DateEdit;
47*cc9bc8c6SJaidyn Ann using BPrivate::TimeEdit;
4878092ae7SKarsten Heimrich 
4978092ae7SKarsten Heimrich 
DateTimeView(const char * name)50323ba9b7SRyan Leavengood DateTimeView::DateTimeView(const char* name)
51323ba9b7SRyan Leavengood 	:
52323ba9b7SRyan Leavengood 	BGroupView(name, B_HORIZONTAL, 5),
531cae077aSStephan Aßmus 	fInitialized(false),
541cae077aSStephan Aßmus 	fSystemTimeAtStart(system_time())
55e4289a54SKarsten Heimrich {
5685b69a94SKarsten Heimrich 	_InitView();
571cae077aSStephan Aßmus 
581cae077aSStephan Aßmus 	// record the current time to enable revert.
591cae077aSStephan Aßmus 	time(&fTimeAtStart);
60e4289a54SKarsten Heimrich }
61e4289a54SKarsten Heimrich 
62e4289a54SKarsten Heimrich 
~DateTimeView()63e4289a54SKarsten Heimrich DateTimeView::~DateTimeView()
64e4289a54SKarsten Heimrich {
65e4289a54SKarsten Heimrich }
66e4289a54SKarsten Heimrich 
67e4289a54SKarsten Heimrich 
68e4289a54SKarsten Heimrich void
AttachedToWindow()69e4289a54SKarsten Heimrich DateTimeView::AttachedToWindow()
70e4289a54SKarsten Heimrich {
71f0650dc9Slooncraz 	AdoptParentColors();
72e4289a54SKarsten Heimrich 
73e4289a54SKarsten Heimrich 	if (!fInitialized) {
74e4289a54SKarsten Heimrich 		fInitialized = true;
7585b69a94SKarsten Heimrich 
7685b69a94SKarsten Heimrich 		fCalendarView->SetTarget(this);
77e4289a54SKarsten Heimrich 	}
78e4289a54SKarsten Heimrich }
79e4289a54SKarsten Heimrich 
80e4289a54SKarsten Heimrich 
81e4289a54SKarsten Heimrich void
MessageReceived(BMessage * message)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 
999dc78758SAkshay Agarwal 		case B_LOCALE_CHANGED:
1009dc78758SAkshay Agarwal 			fCalendarView->UpdateDayNameHeader();
1019dc78758SAkshay Agarwal 			break;
1029dc78758SAkshay Agarwal 
103e4289a54SKarsten Heimrich 		case kDayChanged:
104e4289a54SKarsten Heimrich 		{
105e4289a54SKarsten Heimrich 			BMessage msg(*message);
106e4289a54SKarsten Heimrich 			msg.what = H_USER_CHANGE;
107e4289a54SKarsten Heimrich 			msg.AddBool("time", false);
108e4289a54SKarsten Heimrich 			Window()->PostMessage(&msg);
1091cae077aSStephan Aßmus 			break;
1101cae077aSStephan Aßmus 		}
111e4289a54SKarsten Heimrich 
1121cae077aSStephan Aßmus 		case kMsgRevert:
1131cae077aSStephan Aßmus 			_Revert();
114e4289a54SKarsten Heimrich 			break;
115e4289a54SKarsten Heimrich 
1163e58fe9eSStephan Aßmus 		case kChangeTimeFinished:
1173e58fe9eSStephan Aßmus 			if (fClock->IsChangingTime())
1183e58fe9eSStephan Aßmus 				fTimeEdit->MakeFocus(false);
1193e58fe9eSStephan Aßmus 			fClock->ChangeTimeFinished();
1203e58fe9eSStephan Aßmus 			break;
121d3bde5deSAxel Dörfler 
122c2f3ee3bSAdrien Destugues 		case kRTCUpdate:
123c2f3ee3bSAdrien Destugues 			break;
124c2f3ee3bSAdrien Destugues 
125e4289a54SKarsten Heimrich 		default:
126e4289a54SKarsten Heimrich 			BView::MessageReceived(message);
127e4289a54SKarsten Heimrich 			break;
128e4289a54SKarsten Heimrich 	}
129e4289a54SKarsten Heimrich }
130e4289a54SKarsten Heimrich 
131e4289a54SKarsten Heimrich 
132310930fdSStephan Aßmus bool
CheckCanRevert()1331cae077aSStephan Aßmus DateTimeView::CheckCanRevert()
1341cae077aSStephan Aßmus {
1351cae077aSStephan Aßmus 	// check for changed time
1361cae077aSStephan Aßmus 	time_t unchangedNow = fTimeAtStart + _PrefletUptime();
1371cae077aSStephan Aßmus 	time_t changedNow;
1381cae077aSStephan Aßmus 	time(&changedNow);
1391cae077aSStephan Aßmus 
140c2f3ee3bSAdrien Destugues 	return changedNow != unchangedNow;
1411cae077aSStephan Aßmus }
1421cae077aSStephan Aßmus 
1431cae077aSStephan Aßmus 
1441cae077aSStephan Aßmus void
_Revert()1451cae077aSStephan Aßmus DateTimeView::_Revert()
1461cae077aSStephan Aßmus {
1471cae077aSStephan Aßmus 	// Set the clock and calendar as they were at launch time +
148d3bde5deSAxel Dörfler 	// time elapsed since application launch.
1491cae077aSStephan Aßmus 
1501cae077aSStephan Aßmus 	time_t timeNow = fTimeAtStart + _PrefletUptime();
1511cae077aSStephan Aßmus 	struct tm result;
1521cae077aSStephan Aßmus 	struct tm* timeInfo;
1531cae077aSStephan Aßmus 	timeInfo = localtime_r(&timeNow, &result);
1541cae077aSStephan Aßmus 
1551cae077aSStephan Aßmus 	BDateTime dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
1561cae077aSStephan Aßmus 	BTime time = dateTime.Time();
1571cae077aSStephan Aßmus 	BDate date = dateTime.Date();
1581cae077aSStephan Aßmus 	time.SetTime(timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec % 60);
1591cae077aSStephan Aßmus 	date.SetDate(timeInfo->tm_year + 1900, timeInfo->tm_mon + 1,
1601cae077aSStephan Aßmus 		timeInfo->tm_mday);
1611cae077aSStephan Aßmus 	dateTime.SetTime(time);
1621cae077aSStephan Aßmus 	dateTime.SetDate(date);
1631cae077aSStephan Aßmus 
1641cae077aSStephan Aßmus 	set_real_time_clock(dateTime.Time_t());
1651cae077aSStephan Aßmus }
1661cae077aSStephan Aßmus 
1671cae077aSStephan Aßmus 
1681cae077aSStephan Aßmus time_t
_PrefletUptime() const1691cae077aSStephan Aßmus DateTimeView::_PrefletUptime() const
1701cae077aSStephan Aßmus {
1711cae077aSStephan Aßmus 	return (time_t)((system_time() - fSystemTimeAtStart) / 1000000);
1721cae077aSStephan Aßmus }
1731cae077aSStephan Aßmus 
1741cae077aSStephan Aßmus 
1751cae077aSStephan Aßmus void
_InitView()176e4289a54SKarsten Heimrich DateTimeView::_InitView()
177e4289a54SKarsten Heimrich {
1786846765fSOliver Tappe 	fCalendarView = new BCalendarView("calendar");
179e4289a54SKarsten Heimrich 	fCalendarView->SetWeekNumberHeaderVisible(false);
180e4289a54SKarsten Heimrich 	fCalendarView->SetSelectionMessage(new BMessage(kDayChanged));
181e4289a54SKarsten Heimrich 	fCalendarView->SetInvocationMessage(new BMessage(kDayChanged));
182e4289a54SKarsten Heimrich 
183*cc9bc8c6SJaidyn Ann 	fDateEdit = new DateEdit("dateEdit", 3, new BMessage(H_USER_CHANGE));
184*cc9bc8c6SJaidyn Ann 	fTimeEdit = new TimeEdit("timeEdit", 5, new BMessage(H_USER_CHANGE));
185323ba9b7SRyan Leavengood 	fClock = new TAnalogClock("analogClock");
186e4289a54SKarsten Heimrich 
18778092ae7SKarsten Heimrich 	BTime time(BTime::CurrentTime(B_LOCAL_TIME));
18878092ae7SKarsten Heimrich 	fClock->SetTime(time.Hour(), time.Minute(), time.Second());
189e4289a54SKarsten Heimrich 
190323ba9b7SRyan Leavengood 	BBox* divider = new BBox(BRect(0, 0, 1, 1),
191323ba9b7SRyan Leavengood 		B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
192323ba9b7SRyan Leavengood 		B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER);
193323ba9b7SRyan Leavengood 	divider->SetExplicitMaxSize(BSize(1, B_SIZE_UNLIMITED));
194323ba9b7SRyan Leavengood 
195ad926b25SHumdinger 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, B_USE_DEFAULT_SPACING)
196ad926b25SHumdinger 		.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
197323ba9b7SRyan Leavengood 			.Add(fDateEdit)
198323ba9b7SRyan Leavengood 			.Add(fCalendarView)
199323ba9b7SRyan Leavengood 		.End()
200323ba9b7SRyan Leavengood 		.Add(divider)
201ad926b25SHumdinger 		.AddGroup(B_VERTICAL)
202323ba9b7SRyan Leavengood 			.Add(fTimeEdit)
203323ba9b7SRyan Leavengood 			.Add(fClock)
204323ba9b7SRyan Leavengood 		.End()
205ad926b25SHumdinger 		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
206ad926b25SHumdinger 			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING);
207e4289a54SKarsten Heimrich }
208e4289a54SKarsten Heimrich 
209e4289a54SKarsten Heimrich 
210e4289a54SKarsten Heimrich void
_UpdateDateTime(BMessage * message)211e4289a54SKarsten Heimrich DateTimeView::_UpdateDateTime(BMessage* message)
212e4289a54SKarsten Heimrich {
213e4289a54SKarsten Heimrich 	int32 day;
214e4289a54SKarsten Heimrich 	int32 month;
215e4289a54SKarsten Heimrich 	int32 year;
216e4289a54SKarsten Heimrich 	if (message->FindInt32("month", &month) == B_OK
217e4289a54SKarsten Heimrich 		&& message->FindInt32("day", &day) == B_OK
218d3bde5deSAxel Dörfler 		&& message->FindInt32("year", &year) == B_OK) {
2196846765fSOliver Tappe 		static int32 lastDay;
2206846765fSOliver Tappe 		static int32 lastMonth;
2216846765fSOliver Tappe 		static int32 lastYear;
2226846765fSOliver Tappe 		if (day != lastDay || month != lastMonth || year != lastYear) {
223e4289a54SKarsten Heimrich 			fDateEdit->SetDate(year, month, day);
224e4289a54SKarsten Heimrich 			fCalendarView->SetDate(year, month, day);
2256846765fSOliver Tappe 			lastDay = day;
2266846765fSOliver Tappe 			lastMonth = month;
2276846765fSOliver Tappe 			lastYear = year;
2286846765fSOliver Tappe 		}
229e4289a54SKarsten Heimrich 	}
230e4289a54SKarsten Heimrich 
231e4289a54SKarsten Heimrich 	int32 hour;
232e4289a54SKarsten Heimrich 	int32 minute;
233e4289a54SKarsten Heimrich 	int32 second;
234e4289a54SKarsten Heimrich 	if (message->FindInt32("hour", &hour) == B_OK
235e4289a54SKarsten Heimrich 		&& message->FindInt32("minute", &minute) == B_OK
236d3bde5deSAxel Dörfler 		&& message->FindInt32("second", &second) == B_OK) {
237e4289a54SKarsten Heimrich 		fClock->SetTime(hour, minute, second);
23885b69a94SKarsten Heimrich 		fTimeEdit->SetTime(hour, minute, second);
239e4289a54SKarsten Heimrich 	}
240e4289a54SKarsten Heimrich }
241f64b502dSRyan Leavengood 
242