xref: /haiku/src/preferences/locale/FormatSettingsView.cpp (revision 99d027cd0238c1d86da86d7c3f4200509ccc61a6)
1 /*
2  * Copyright 2009, Adrien Destugues, pulkomandy@gmail.com. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "FormatSettingsView.h"
8 
9 #include <stdlib.h>
10 
11 #include <Alert.h>
12 #include <Application.h>
13 #include <Catalog.h>
14 #include <CheckBox.h>
15 #include <ControlLook.h>
16 #include <GridLayout.h>
17 #include <GridLayoutBuilder.h>
18 #include <GroupLayout.h>
19 #include <GroupLayoutBuilder.h>
20 #include <LayoutBuilder.h>
21 #include <Locale.h>
22 #include <MutableLocaleRoster.h>
23 #include <Message.h>
24 #include <Menu.h>
25 #include <MenuField.h>
26 #include <MenuItem.h>
27 #include <PopUpMenu.h>
28 #include <RadioButton.h>
29 #include <ScrollView.h>
30 #include <ScrollBar.h>
31 #include <SeparatorView.h>
32 #include <SpaceLayoutItem.h>
33 #include <String.h>
34 #include <StringView.h>
35 #include <TextControl.h>
36 #include <Window.h>
37 
38 #include "LocalePreflet.h"
39 
40 
41 using BPrivate::MutableLocaleRoster;
42 
43 
44 #undef B_TRANSLATION_CONTEXT
45 #define B_TRANSLATION_CONTEXT "TimeFormatSettings"
46 
47 
48 // #pragma mark -
49 
50 
51 FormatSettingsView::FormatSettingsView()
52 	:
53 	BView("WindowsSettingsView", B_FRAME_EVENTS)
54 {
55 	fUseLanguageStringsCheckBox = new BCheckBox(
56 		B_TRANSLATE("Use month/day-names from preferred language"),
57 		new BMessage(kStringsLanguageChange));
58 
59 	BStringView* fullDateLabel
60 		= new BStringView("", B_TRANSLATE("Full format:"));
61 	fullDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
62 		B_ALIGN_VERTICAL_UNSET));
63 	BStringView* longDateLabel
64 		= new BStringView("", B_TRANSLATE("Long format:"));
65 	longDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
66 		B_ALIGN_VERTICAL_UNSET));
67 	BStringView* mediumDateLabel
68 		= new BStringView("", B_TRANSLATE("Medium format:"));
69 	mediumDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
70 		B_ALIGN_VERTICAL_UNSET));
71 	BStringView* shortDateLabel
72 		= new BStringView("", B_TRANSLATE("Short format:"));
73 	shortDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
74 		B_ALIGN_VERTICAL_UNSET));
75 
76 	fFullDateExampleView = new BStringView("", "");
77 	fFullDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
78 		B_ALIGN_VERTICAL_UNSET));
79 	fLongDateExampleView = new BStringView("", "");
80 	fLongDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
81 		B_ALIGN_VERTICAL_UNSET));
82 	fMediumDateExampleView = new BStringView("", "");
83 	fMediumDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
84 		B_ALIGN_VERTICAL_UNSET));
85 	fShortDateExampleView = new BStringView("", "");
86 	fShortDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
87 		B_ALIGN_VERTICAL_UNSET));
88 
89 	f24HourRadioButton = new BRadioButton("", B_TRANSLATE("24 hour"),
90 		new BMessage(kClockFormatChange));
91 	f12HourRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"),
92 		new BMessage(kClockFormatChange));
93 
94 	float spacing = be_control_look->DefaultItemSpacing();
95 
96 	BStringView* fullTimeLabel
97 		= new BStringView("", B_TRANSLATE("Full format:"));
98 	fullTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
99 		B_ALIGN_VERTICAL_UNSET));
100 	BStringView* longTimeLabel
101 		= new BStringView("", B_TRANSLATE("Long format:"));
102 	longTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
103 		B_ALIGN_VERTICAL_UNSET));
104 	BStringView* mediumTimeLabel
105 		= new BStringView("", B_TRANSLATE("Medium format:"));
106 	mediumTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
107 		B_ALIGN_VERTICAL_UNSET));
108 	BStringView* shortTimeLabel
109 		= new BStringView("", B_TRANSLATE("Short format:"));
110 	shortTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
111 		B_ALIGN_VERTICAL_UNSET));
112 
113 	fFullTimeExampleView = new BStringView("", "");
114 	fFullTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
115 		B_ALIGN_VERTICAL_UNSET));
116 	fLongTimeExampleView = new BStringView("", "");
117 	fLongTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
118 		B_ALIGN_VERTICAL_UNSET));
119 	fMediumTimeExampleView = new BStringView("", "");
120 	fMediumTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
121 		B_ALIGN_VERTICAL_UNSET));
122 	fShortTimeExampleView = new BStringView("", "");
123 	fShortTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
124 		B_ALIGN_VERTICAL_UNSET));
125 
126 	BStringView* positiveNumberLabel
127 		= new BStringView("", B_TRANSLATE("Positive:"));
128 	positiveNumberLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
129 		B_ALIGN_VERTICAL_UNSET));
130 	BStringView* negativeNumberLabel
131 		= new BStringView("", B_TRANSLATE("Negative:"));
132 	negativeNumberLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
133 		B_ALIGN_VERTICAL_UNSET));
134 
135 	fPositiveNumberExampleView = new BStringView("", "");
136 	fPositiveNumberExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT,
137 		B_ALIGN_VERTICAL_UNSET));
138 	fNegativeNumberExampleView = new BStringView("", "");
139 	fNegativeNumberExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT,
140 		B_ALIGN_VERTICAL_UNSET));
141 
142 	BStringView* positiveMonetaryLabel
143 		= new BStringView("", B_TRANSLATE("Positive:"));
144 	positiveMonetaryLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
145 		B_ALIGN_VERTICAL_UNSET));
146 	BStringView* negativeMonetaryLabel
147 		= new BStringView("", B_TRANSLATE("Negative:"));
148 	negativeMonetaryLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
149 		B_ALIGN_VERTICAL_UNSET));
150 
151 	fPositiveMonetaryExampleView = new BStringView("", "");
152 	fPositiveMonetaryExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT,
153 		B_ALIGN_VERTICAL_UNSET));
154 	fNegativeMonetaryExampleView = new BStringView("", "");
155 	fNegativeMonetaryExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT,
156 		B_ALIGN_VERTICAL_UNSET));
157 
158 	Refresh(true);
159 
160 	fDateBox = new BBox(B_TRANSLATE("Date"));
161 	fTimeBox = new BBox(B_TRANSLATE("Time"));
162 	fNumberBox = new BBox(B_TRANSLATE("Numbers"));
163 	fMonetaryBox = new BBox(B_TRANSLATE("Currency"));
164 
165 	fDateBox->SetLabel(B_TRANSLATE("Date"));
166 	fTimeBox->SetLabel(B_TRANSLATE("Time"));
167 	fNumberBox->SetLabel(B_TRANSLATE("Numbers"));
168 	fMonetaryBox->SetLabel(B_TRANSLATE("Currency"));
169 
170 	fDateBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2)
171 		.SetInsets(spacing, spacing, spacing, spacing)
172 		.Add(fullDateLabel, 0, 0)
173 		.Add(fFullDateExampleView, 1, 0)
174 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 0)
175 		.Add(longDateLabel, 0, 1)
176 		.Add(fLongDateExampleView, 1, 1)
177 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 1)
178 		.Add(mediumDateLabel, 0, 2)
179 		.Add(fMediumDateExampleView, 1, 2)
180 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 2)
181 		.Add(shortDateLabel, 0, 3)
182 		.Add(fShortDateExampleView, 1, 3)
183 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 3)
184 		.View());
185 
186 	fTimeBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2)
187 		.SetInsets(spacing, spacing, spacing, spacing)
188 		.AddGroup(B_HORIZONTAL, spacing, 0, 0, 2)
189 			.Add(f24HourRadioButton, 0)
190 			.Add(f12HourRadioButton, 0)
191 			.AddGlue()
192 			.End()
193 		.Add(fullTimeLabel, 0, 1)
194 		.Add(fFullTimeExampleView, 1, 1)
195 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 1)
196 		.Add(longTimeLabel, 0, 2)
197 		.Add(fLongTimeExampleView, 1, 2)
198 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 2)
199 		.Add(mediumTimeLabel, 0, 3)
200 		.Add(fMediumTimeExampleView, 1, 3)
201 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 3)
202 		.Add(shortTimeLabel, 0, 4)
203 		.Add(fShortTimeExampleView, 1, 4)
204 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 4)
205 		.View());
206 
207 	fNumberBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2)
208 		.SetInsets(spacing, spacing, spacing, spacing)
209 		.Add(positiveNumberLabel, 0, 0)
210 		.Add(fPositiveNumberExampleView, 1, 0)
211 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 0)
212 		.Add(negativeNumberLabel, 0, 1)
213 		.Add(fNegativeNumberExampleView, 1, 1)
214 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 1)
215 		.View());
216 
217 	fMonetaryBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2)
218 		.SetInsets(spacing, spacing, spacing, spacing)
219 		.Add(positiveMonetaryLabel, 0, 0)
220 		.Add(fPositiveMonetaryExampleView, 1, 0)
221 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 0)
222 		.Add(negativeMonetaryLabel, 0, 1)
223 		.Add(fNegativeMonetaryExampleView, 1, 1)
224 		.Add(BSpaceLayoutItem::CreateGlue(), 2, 1)
225 		.View());
226 
227 	BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL, spacing);
228 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
229 	SetLayout(rootLayout);
230 	BLayoutBuilder::Group<>(rootLayout)
231 		.Add(fUseLanguageStringsCheckBox)
232 		.Add(fDateBox)
233 		.Add(fTimeBox)
234 		.AddGroup(B_HORIZONTAL, spacing)
235 			.Add(fNumberBox)
236 			.Add(fMonetaryBox)
237 			.AddGlue()
238 			.End()
239 		.AddGlue();
240 }
241 
242 
243 FormatSettingsView::~FormatSettingsView()
244 {
245 }
246 
247 
248 void
249 FormatSettingsView::AttachedToWindow()
250 {
251 	fUseLanguageStringsCheckBox->SetTarget(this);
252 	f24HourRadioButton->SetTarget(this);
253 	f12HourRadioButton->SetTarget(this);
254 }
255 
256 
257 void
258 FormatSettingsView::MessageReceived(BMessage* message)
259 {
260 	switch (message->what) {
261 		case kClockFormatChange:
262 		{
263 			BFormattingConventions conventions;
264 			BLocale::Default()->GetFormattingConventions(&conventions);
265 			conventions.SetExplicitUse24HourClock(
266 				f24HourRadioButton->Value() ? true : false);
267 			MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
268 				conventions);
269 
270 			_UpdateExamples();
271 			Window()->PostMessage(kMsgSettingsChanged);
272 			break;
273 		}
274 
275 		case kStringsLanguageChange:
276 		{
277 			BFormattingConventions conventions;
278 			BLocale::Default()->GetFormattingConventions(&conventions);
279 			conventions.SetUseStringsFromPreferredLanguage(
280 				fUseLanguageStringsCheckBox->Value() ? true : false);
281 			MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
282 				conventions);
283 
284 			_UpdateExamples();
285 
286 			Window()->PostMessage(kMsgSettingsChanged);
287 			break;
288 		}
289 
290 		default:
291 			BView::MessageReceived(message);
292 	}
293 }
294 
295 
296 void
297 FormatSettingsView::Revert()
298 {
299 	MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
300 		fInitialConventions);
301 
302 	_UpdateExamples();
303 }
304 
305 
306 void
307 FormatSettingsView::Refresh(bool setInitial)
308 {
309 	BFormattingConventions conventions;
310 	BLocale::Default()->GetFormattingConventions(&conventions);
311 	if (setInitial)
312 		fInitialConventions = conventions;
313 
314 	if (!conventions.Use24HourClock()) {
315 		f12HourRadioButton->SetValue(B_CONTROL_ON);
316 		fLocaleIs24Hour = false;
317 	} else {
318 		f24HourRadioButton->SetValue(B_CONTROL_ON);
319 		fLocaleIs24Hour = true;
320 	}
321 
322 	fUseLanguageStringsCheckBox->SetValue(
323 		conventions.UseStringsFromPreferredLanguage()
324 			? B_CONTROL_ON : B_CONTROL_OFF);
325 
326 	_UpdateExamples();
327 }
328 
329 
330 // Return true if the Revert button should be enabled (i.e. something has been
331 // changed)
332 bool
333 FormatSettingsView::IsReversible() const
334 {
335 	BFormattingConventions conventions;
336 	BLocale::Default()->GetFormattingConventions(&conventions);
337 
338 	return conventions != fInitialConventions;
339 }
340 
341 
342 void
343 FormatSettingsView::_UpdateExamples()
344 {
345 	time_t timeValue = (time_t)time(NULL);
346 	BString result;
347 
348 	BLocale::Default()->FormatDate(&result, timeValue, B_FULL_DATE_FORMAT);
349 	fFullDateExampleView->SetText(result);
350 
351 	BLocale::Default()->FormatDate(&result, timeValue, B_LONG_DATE_FORMAT);
352 	fLongDateExampleView->SetText(result);
353 
354 	BLocale::Default()->FormatDate(&result, timeValue, B_MEDIUM_DATE_FORMAT);
355 	fMediumDateExampleView->SetText(result);
356 
357 	BLocale::Default()->FormatDate(&result, timeValue, B_SHORT_DATE_FORMAT);
358 	fShortDateExampleView->SetText(result);
359 
360 	BLocale::Default()->FormatTime(&result, timeValue, B_FULL_TIME_FORMAT);
361 	fFullTimeExampleView->SetText(result);
362 
363 	BLocale::Default()->FormatTime(&result, timeValue, B_LONG_TIME_FORMAT);
364 	fLongTimeExampleView->SetText(result);
365 
366 	BLocale::Default()->FormatTime(&result, timeValue, B_MEDIUM_TIME_FORMAT);
367 	fMediumTimeExampleView->SetText(result);
368 
369 	BLocale::Default()->FormatTime(&result, timeValue, B_SHORT_TIME_FORMAT);
370 	fShortTimeExampleView->SetText(result);
371 
372 	status_t status = BLocale::Default()->FormatNumber(&result, 1234.5678);
373 	if (status == B_OK)
374 		fPositiveNumberExampleView->SetText(result);
375 	else
376 		fPositiveNumberExampleView->SetText("ERROR");
377 
378 	status = BLocale::Default()->FormatNumber(&result, -1234.5678);
379 	if (status == B_OK)
380 		fNegativeNumberExampleView->SetText(result);
381 	else
382 		fNegativeNumberExampleView->SetText("ERROR");
383 
384 	status = BLocale::Default()->FormatMonetary(&result, 1234.56);
385 	if (status == B_OK)
386 		fPositiveMonetaryExampleView->SetText(result);
387 	else
388 		fPositiveMonetaryExampleView->SetText("ERROR");
389 
390 	status = BLocale::Default()->FormatMonetary(&result, -1234.56);
391 	if (status == B_OK)
392 		fNegativeMonetaryExampleView->SetText(result);
393 	else
394 		fNegativeMonetaryExampleView->SetText("ERROR");
395 }
396