xref: /haiku/src/preferences/time/DateTimeView.cpp (revision 6f80a9801fedbe7355c4360bd204ba746ec3ec2d)
1 /*
2  * Copyright 2004-2011, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Andrew McCall <mccall@@digitalparadise.co.uk>
7  *		Mike Berg <mike@berg-net.us>
8  *		Julun <host.haiku@gmx.de>
9  *		Philippe Saint-Pierre <stpere@gmail.com>
10  *		Hamish Morrison <hamish@lavabit.com>
11  */
12 
13 #include "DateTimeView.h"
14 
15 #include <time.h>
16 #include <syscalls.h>
17 
18 #include <Box.h>
19 #include <CalendarView.h>
20 #include <Catalog.h>
21 #include <CheckBox.h>
22 #include <ControlLook.h>
23 #include <DateTime.h>
24 #include <DateTimeEdit.h>
25 #include <Entry.h>
26 #include <File.h>
27 #include <FindDirectory.h>
28 #include <LocaleRoster.h>
29 #include <Message.h>
30 #include <Path.h>
31 #include <StringView.h>
32 #include <Window.h>
33 
34 #include "AnalogClock.h"
35 #include "TimeMessages.h"
36 #include "TimeWindow.h"
37 
38 
39 #undef B_TRANSLATION_CONTEXT
40 #define B_TRANSLATION_CONTEXT "Time"
41 
42 
43 using BPrivate::BCalendarView;
44 using BPrivate::BDateTime;
45 using BPrivate::B_LOCAL_TIME;
46 using BPrivate::DateEdit;
47 using BPrivate::TimeEdit;
48 
49 
50 DateTimeView::DateTimeView(const char* name)
51 	:
52 	BGroupView(name, B_HORIZONTAL, 5),
53 	fInitialized(false),
54 	fSystemTimeAtStart(system_time())
55 {
56 	_InitView();
57 
58 	// record the current time to enable revert.
59 	time(&fTimeAtStart);
60 }
61 
62 
63 DateTimeView::~DateTimeView()
64 {
65 }
66 
67 
68 void
69 DateTimeView::AttachedToWindow()
70 {
71 	AdoptParentColors();
72 
73 	if (!fInitialized) {
74 		fInitialized = true;
75 
76 		fCalendarView->SetTarget(this);
77 	}
78 }
79 
80 
81 void
82 DateTimeView::MessageReceived(BMessage* message)
83 {
84 	int32 change;
85 	switch (message->what) {
86 		case B_OBSERVER_NOTICE_CHANGE:
87 			message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change);
88 			switch (change) {
89 				case H_TM_CHANGED:
90 					_UpdateDateTime(message);
91 					break;
92 
93 				default:
94 					BView::MessageReceived(message);
95 					break;
96 			}
97 			break;
98 
99 		case B_LOCALE_CHANGED:
100 			fCalendarView->UpdateDayNameHeader();
101 			break;
102 
103 		case kDayChanged:
104 		{
105 			BMessage msg(*message);
106 			msg.what = H_USER_CHANGE;
107 			msg.AddBool("time", false);
108 			Window()->PostMessage(&msg);
109 			break;
110 		}
111 
112 		case kMsgRevert:
113 			_Revert();
114 			break;
115 
116 		case kChangeTimeFinished:
117 			if (fClock->IsChangingTime())
118 				fTimeEdit->MakeFocus(false);
119 			fClock->ChangeTimeFinished();
120 			break;
121 
122 		case kRTCUpdate:
123 			break;
124 
125 		default:
126 			BView::MessageReceived(message);
127 			break;
128 	}
129 }
130 
131 
132 bool
133 DateTimeView::CheckCanRevert()
134 {
135 	// check for changed time
136 	time_t unchangedNow = fTimeAtStart + _PrefletUptime();
137 	time_t changedNow;
138 	time(&changedNow);
139 
140 	return changedNow != unchangedNow;
141 }
142 
143 
144 void
145 DateTimeView::_Revert()
146 {
147 	// Set the clock and calendar as they were at launch time +
148 	// time elapsed since application launch.
149 
150 	time_t timeNow = fTimeAtStart + _PrefletUptime();
151 	struct tm result;
152 	struct tm* timeInfo;
153 	timeInfo = localtime_r(&timeNow, &result);
154 
155 	BDateTime dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
156 	BTime time = dateTime.Time();
157 	BDate date = dateTime.Date();
158 	time.SetTime(timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec % 60);
159 	date.SetDate(timeInfo->tm_year + 1900, timeInfo->tm_mon + 1,
160 		timeInfo->tm_mday);
161 	dateTime.SetTime(time);
162 	dateTime.SetDate(date);
163 
164 	set_real_time_clock(dateTime.Time_t());
165 }
166 
167 
168 time_t
169 DateTimeView::_PrefletUptime() const
170 {
171 	return (time_t)((system_time() - fSystemTimeAtStart) / 1000000);
172 }
173 
174 
175 void
176 DateTimeView::_InitView()
177 {
178 	fCalendarView = new BCalendarView("calendar");
179 	fCalendarView->SetWeekNumberHeaderVisible(false);
180 	fCalendarView->SetSelectionMessage(new BMessage(kDayChanged));
181 	fCalendarView->SetInvocationMessage(new BMessage(kDayChanged));
182 
183 	fDateEdit = new DateEdit("dateEdit", 3, new BMessage(H_USER_CHANGE));
184 	fTimeEdit = new TimeEdit("timeEdit", 5, new BMessage(H_USER_CHANGE));
185 	fClock = new TAnalogClock("analogClock");
186 
187 	BTime time(BTime::CurrentTime(B_LOCAL_TIME));
188 	fClock->SetTime(time.Hour(), time.Minute(), time.Second());
189 
190 	BBox* divider = new BBox(BRect(0, 0, 1, 1),
191 		B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
192 		B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER);
193 	divider->SetExplicitMaxSize(BSize(1, B_SIZE_UNLIMITED));
194 
195 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, B_USE_DEFAULT_SPACING)
196 		.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
197 			.Add(fDateEdit)
198 			.Add(fCalendarView)
199 		.End()
200 		.Add(divider)
201 		.AddGroup(B_VERTICAL)
202 			.Add(fTimeEdit)
203 			.Add(fClock)
204 		.End()
205 		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
206 			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING);
207 }
208 
209 
210 void
211 DateTimeView::_UpdateDateTime(BMessage* message)
212 {
213 	int32 day;
214 	int32 month;
215 	int32 year;
216 	if (message->FindInt32("month", &month) == B_OK
217 		&& message->FindInt32("day", &day) == B_OK
218 		&& message->FindInt32("year", &year) == B_OK) {
219 		static int32 lastDay;
220 		static int32 lastMonth;
221 		static int32 lastYear;
222 		if (day != lastDay || month != lastMonth || year != lastYear) {
223 			fDateEdit->SetDate(year, month, day);
224 			fCalendarView->SetDate(year, month, day);
225 			lastDay = day;
226 			lastMonth = month;
227 			lastYear = year;
228 		}
229 	}
230 
231 	int32 hour;
232 	int32 minute;
233 	int32 second;
234 	if (message->FindInt32("hour", &hour) == B_OK
235 		&& message->FindInt32("minute", &minute) == B_OK
236 		&& message->FindInt32("second", &second) == B_OK) {
237 		fClock->SetTime(hour, minute, second);
238 		fTimeEdit->SetTime(hour, minute, second);
239 	}
240 }
241 
242