xref: /haiku/src/preferences/time/DateTimeView.cpp (revision d9cebac2b77547b7064f22497514eecd2d047160)
1 /*
2  * Copyright 2004-2007, 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  */
10 
11 #include "DateTimeView.h"
12 #include "AnalogClock.h"
13 #include "CalendarView.h"
14 #include "DateTimeEdit.h"
15 #include "TimeMessages.h"
16 
17 
18 #include <CheckBox.h>
19 #include <Entry.h>
20 #include <File.h>
21 #include <FindDirectory.h>
22 #include <Message.h>
23 #include <Path.h>
24 #include <RadioButton.h>
25 #include <String.h>
26 #include <StringView.h>
27 #include <Window.h>
28 
29 
30 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
31 #	include <syscalls.h>
32 #else
33 extern "C" void _kset_tzfilename_(const char *name, size_t length, bool isGMT);
34 #	define _kern_set_tzfilename _kset_tzfilename_
35 #endif
36 
37 
38 DateTimeView::DateTimeView(BRect frame)
39 	: BView(frame, "dateTimeView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP),
40 	  fGmtTime(NULL),
41 	  fUseGmtTime(false),
42 	  fInitialized(false)
43 {
44 	_ReadRTCSettings();
45 	_InitView();
46 }
47 
48 
49 DateTimeView::~DateTimeView()
50 {
51 	_WriteRTCSettings();
52 }
53 
54 
55 void
56 DateTimeView::AttachedToWindow()
57 {
58 	if (Parent())
59 		SetViewColor(Parent()->ViewColor());
60 
61 	if (!fInitialized) {
62 		fInitialized = true;
63 
64 		fGmtTime->SetTarget(this);
65 		fLocalTime->SetTarget(this);
66 		fCalendarView->SetTarget(this);
67 	}
68 }
69 
70 
71 void
72 DateTimeView::Draw(BRect /*updateRect*/)
73 {
74 	rgb_color viewcolor = ViewColor();
75 	rgb_color dark = tint_color(viewcolor, B_DARKEN_4_TINT);
76 	rgb_color light = tint_color(viewcolor, B_LIGHTEN_MAX_TINT);
77 
78 	//draw a separator line
79 	BRect bounds(Bounds());
80 	BPoint start(bounds.Width() / 2.0f, bounds.top + 5.0f);
81 	BPoint end(bounds.Width() / 2.0, bounds.bottom - 5.0f);
82 
83 	BeginLineArray(2);
84 		AddLine(start, end, dark);
85 		start.x++;
86 		end.x++;
87 		AddLine(start, end, light);
88 	EndLineArray();
89 
90 	fTimeEdit->Draw(bounds);
91 	fDateEdit->Draw(bounds);
92 }
93 
94 
95 void
96 DateTimeView::MessageReceived(BMessage *message)
97 {
98 	int32 change;
99 	switch(message->what) {
100 		case B_OBSERVER_NOTICE_CHANGE:
101 			message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change);
102 			switch(change) {
103 				case H_TM_CHANGED:
104 					_UpdateDateTime(message);
105 				break;
106 
107 				default:
108 					BView::MessageReceived(message);
109 				break;
110 			}
111 		break;
112 
113 		case kDayChanged:
114 		{
115 			BMessage msg(*message);
116 			msg.what = H_USER_CHANGE;
117 			msg.AddBool("time", false);
118 			Window()->PostMessage(&msg);
119 		}	break;
120 
121 		case kRTCUpdate:
122 			fUseGmtTime = !fUseGmtTime;
123 			_UpdateGmtSettings();
124 			break;
125 
126 		default:
127 			BView::MessageReceived(message);
128 			break;
129 	}
130 }
131 
132 
133 void
134 DateTimeView::_InitView()
135 {
136 	font_height fontHeight;
137 	be_plain_font->GetHeight(&fontHeight);
138 	float textHeight = fontHeight.descent + fontHeight.ascent
139 		+ fontHeight.leading + 6.0;	// 6px border
140 
141 	// left side
142 	BRect bounds = Bounds();
143 	bounds.InsetBy(10.0, 10.0);
144 	bounds.top += textHeight + 10.0;
145 
146 	fCalendarView = new BCalendarView(bounds, "calendar");
147 	fCalendarView->SetWeekNumberHeaderVisible(false);
148 	fCalendarView->ResizeToPreferred();
149 	fCalendarView->SetSelectionMessage(new BMessage(kDayChanged));
150 	fCalendarView->SetInvocationMessage(new BMessage(kDayChanged));
151 
152 	bounds.top -= textHeight + 10.0;
153 	bounds.bottom = bounds.top + textHeight;
154 	bounds.right = fCalendarView->Frame().right;
155 
156 	fDateEdit = new TDateEdit(bounds, "dateEdit", 3);
157 	AddChild(fDateEdit);
158 	AddChild(fCalendarView);
159 
160 	// right side, 2px extra for separator
161 	bounds.OffsetBy(bounds.Width() + 22.0, 0.0);
162 	fTimeEdit = new TTimeEdit(bounds, "timeEdit", 4);
163 	AddChild(fTimeEdit);
164 
165 	bounds = fCalendarView->Frame();
166 	bounds.OffsetBy(bounds.Width() + 22.0, 0.0);
167 
168 	fClock = new TAnalogClock(bounds, "analogClock");
169 	AddChild(fClock);
170 
171 	// clock radio buttons
172 	bounds.top = fClock->Frame().bottom + 10.0;
173 	BStringView *text = new BStringView(bounds, "clockSetTo", "Clock set to:");
174 	AddChild(text);
175 	text->ResizeToPreferred();
176 
177 	bounds.left += 10.0f;
178 	bounds.top = text->Frame().bottom;
179 	fLocalTime = new BRadioButton(bounds, "localTime", "Local Time",
180 		new BMessage(kRTCUpdate));
181 	AddChild(fLocalTime);
182 	fLocalTime->ResizeToPreferred();
183 
184 	bounds.left = fLocalTime->Frame().right + 10.0;
185 	fGmtTime = new BRadioButton(bounds, "greenwichMeanTime", "GMT",
186 		new BMessage(kRTCUpdate));
187 	AddChild(fGmtTime);
188 	fGmtTime->ResizeToPreferred();
189 
190 	if (fUseGmtTime)
191 		fGmtTime->SetValue(B_CONTROL_ON);
192 	else
193 		fLocalTime->SetValue(B_CONTROL_ON);
194 
195 	ResizeTo(fClock->Frame().right + 10.0, fGmtTime->Frame().bottom + 10.0);
196 }
197 
198 
199 void
200 DateTimeView::_ReadRTCSettings()
201 {
202 	BPath path;
203 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
204 		return;
205 
206 	path.Append("RTC_time_settings");
207 
208 	BEntry entry(path.Path());
209 	if (entry.Exists()) {
210 		BFile file(&entry, B_READ_ONLY);
211 		if (file.InitCheck() == B_OK) {
212 			char buffer[6];
213 			file.Read(buffer, 6);
214 			if (strncmp(buffer, "gmt", 3) == 0)
215 				fUseGmtTime = true;
216 		}
217 	} else
218 		_UpdateGmtSettings();
219 }
220 
221 
222 void
223 DateTimeView::_WriteRTCSettings()
224 {
225 	BPath path;
226 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
227 		return;
228 
229 	path.Append("RTC_time_settings");
230 
231 	BFile file(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
232 	if (file.InitCheck() == B_OK) {
233 		if (fUseGmtTime)
234 			file.Write("gmt", 3);
235 		else
236 			file.Write("local", 5);
237 	}
238 }
239 
240 
241 void
242 DateTimeView::_UpdateGmtSettings()
243 {
244 	_WriteRTCSettings();
245 
246 	BPath path;
247 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
248 		return;
249 
250 	path.Append("timezone");
251 	BEntry entry(path.Path(), true);
252 
253 	if (!entry.Exists())
254 		return;
255 
256 	entry.GetPath(&path);
257 
258 	// take the existing timezone and set it's gmt use
259 	_kern_set_tzfilename(path.Path(), B_PATH_NAME_LENGTH, fUseGmtTime);
260 }
261 
262 
263 void
264 DateTimeView::_UpdateDateTime(BMessage *message)
265 {
266 	int32 day;
267 	int32 month;
268 	int32 year;
269 	if (message->FindInt32("month", &month) == B_OK
270 		&& message->FindInt32("day", &day) == B_OK
271 		&& message->FindInt32("year", &year) == B_OK)
272 	{
273 		fDateEdit->SetDate(year, month, day);
274 		fCalendarView->SetDate(year, month, day);
275 	}
276 
277 	int32 hour;
278 	int32 minute;
279 	int32 second;
280 	if (message->FindInt32("hour", &hour) == B_OK
281 		&& message->FindInt32("minute", &minute) == B_OK
282 		&& message->FindInt32("second", &second) == B_OK)
283 	{
284 		fClock->SetTime(hour, minute, second);
285 		fTimeEdit->SetTime(hour, minute, second);
286 	}
287 }
288