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