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
41using BPrivate::MutableLocaleRoster;
42
43
44#undef B_TRANSLATION_CONTEXT
45#define B_TRANSLATION_CONTEXT "TimeFormatSettings"
46
47
48// #pragma mark -
49
50
51FormatSettingsView::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
243FormatSettingsView::~FormatSettingsView()
244{
245}
246
247
248void
249FormatSettingsView::AttachedToWindow()
250{
251	fUseLanguageStringsCheckBox->SetTarget(this);
252	f24HourRadioButton->SetTarget(this);
253	f12HourRadioButton->SetTarget(this);
254}
255
256
257void
258FormatSettingsView::MessageReceived(BMessage* message)
259{
260	switch (message->what) {
261		case B_LOCALE_CHANGED:
262		{
263			// Time updated 12/24 hour clock
264			BFormattingConventions conventions;
265			BLocale::Default()->GetFormattingConventions(&conventions);
266			if (conventions.Use24HourClock())
267				f24HourRadioButton->SetValue(B_CONTROL_ON);
268			else
269				f12HourRadioButton->SetValue(B_CONTROL_ON);
270
271			_UpdateExamples();
272			Window()->PostMessage(kMsgSettingsChanged);
273			break;
274		}
275
276		case kClockFormatChange:
277		{
278			BFormattingConventions conventions;
279			BLocale::Default()->GetFormattingConventions(&conventions);
280			conventions.SetExplicitUse24HourClock(
281				f24HourRadioButton->Value() == B_CONTROL_ON);
282			MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
283				conventions);
284
285			_UpdateExamples();
286			Window()->PostMessage(kMsgSettingsChanged);
287			break;
288		}
289
290		case kStringsLanguageChange:
291		{
292			BFormattingConventions conventions;
293			BLocale::Default()->GetFormattingConventions(&conventions);
294			conventions.SetUseStringsFromPreferredLanguage(
295				fUseLanguageStringsCheckBox->Value() ? true : false);
296			MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
297				conventions);
298
299			_UpdateExamples();
300
301			Window()->PostMessage(kMsgSettingsChanged);
302			break;
303		}
304
305		default:
306			BView::MessageReceived(message);
307	}
308}
309
310
311void
312FormatSettingsView::Revert()
313{
314	MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
315		fInitialConventions);
316
317	_UpdateExamples();
318}
319
320
321void
322FormatSettingsView::Refresh(bool setInitial)
323{
324	BFormattingConventions conventions;
325	BLocale::Default()->GetFormattingConventions(&conventions);
326	if (setInitial)
327		fInitialConventions = conventions;
328
329	if (!conventions.Use24HourClock()) {
330		f12HourRadioButton->SetValue(B_CONTROL_ON);
331		fLocaleIs24Hour = false;
332	} else {
333		f24HourRadioButton->SetValue(B_CONTROL_ON);
334		fLocaleIs24Hour = true;
335	}
336
337	fUseLanguageStringsCheckBox->SetValue(
338		conventions.UseStringsFromPreferredLanguage()
339			? B_CONTROL_ON : B_CONTROL_OFF);
340
341	_UpdateExamples();
342}
343
344
345// Return true if the Revert button should be enabled (i.e. something has been
346// changed)
347bool
348FormatSettingsView::IsReversible() const
349{
350	BFormattingConventions conventions;
351	BLocale::Default()->GetFormattingConventions(&conventions);
352
353	return conventions != fInitialConventions;
354}
355
356
357void
358FormatSettingsView::_UpdateExamples()
359{
360	time_t timeValue = (time_t)time(NULL);
361	BString result;
362
363	BLocale::Default()->FormatDate(&result, timeValue, B_FULL_DATE_FORMAT);
364	fFullDateExampleView->SetText(result);
365
366	BLocale::Default()->FormatDate(&result, timeValue, B_LONG_DATE_FORMAT);
367	fLongDateExampleView->SetText(result);
368
369	BLocale::Default()->FormatDate(&result, timeValue, B_MEDIUM_DATE_FORMAT);
370	fMediumDateExampleView->SetText(result);
371
372	BLocale::Default()->FormatDate(&result, timeValue, B_SHORT_DATE_FORMAT);
373	fShortDateExampleView->SetText(result);
374
375	BLocale::Default()->FormatTime(&result, timeValue, B_FULL_TIME_FORMAT);
376	fFullTimeExampleView->SetText(result);
377
378	BLocale::Default()->FormatTime(&result, timeValue, B_LONG_TIME_FORMAT);
379	fLongTimeExampleView->SetText(result);
380
381	BLocale::Default()->FormatTime(&result, timeValue, B_MEDIUM_TIME_FORMAT);
382	fMediumTimeExampleView->SetText(result);
383
384	BLocale::Default()->FormatTime(&result, timeValue, B_SHORT_TIME_FORMAT);
385	fShortTimeExampleView->SetText(result);
386
387	status_t status = BLocale::Default()->FormatNumber(&result, 1234.5678);
388	if (status == B_OK)
389		fPositiveNumberExampleView->SetText(result);
390	else
391		fPositiveNumberExampleView->SetText("ERROR");
392
393	status = BLocale::Default()->FormatNumber(&result, -1234.5678);
394	if (status == B_OK)
395		fNegativeNumberExampleView->SetText(result);
396	else
397		fNegativeNumberExampleView->SetText("ERROR");
398
399	status = BLocale::Default()->FormatMonetary(&result, 1234.56);
400	if (status == B_OK)
401		fPositiveMonetaryExampleView->SetText(result);
402	else
403		fPositiveMonetaryExampleView->SetText("ERROR");
404
405	status = BLocale::Default()->FormatMonetary(&result, -1234.56);
406	if (status == B_OK)
407		fNegativeMonetaryExampleView->SetText(result);
408	else
409		fNegativeMonetaryExampleView->SetText("ERROR");
410}
411