xref: /haiku/src/preferences/locale/FormatSettingsView.cpp (revision e0bc2fcce4c5ceb7b57d978b752cda01639d0098)
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 #include "Locale.h"
9 
10 #include <Alert.h>
11 #include <Application.h>
12 #include <Catalog.h>
13 #include <CheckBox.h>
14 #include <ControlLook.h>
15 #include <Country.h>
16 #include <GroupLayout.h>
17 #include <GroupLayoutBuilder.h>
18 #include <LayoutBuilder.h>
19 #include <Locale.h>
20 #include <MutableLocaleRoster.h>
21 #include <Message.h>
22 #include <Menu.h>
23 #include <MenuField.h>
24 #include <MenuItem.h>
25 #include <PopUpMenu.h>
26 #include <RadioButton.h>
27 #include <ScrollView.h>
28 #include <ScrollBar.h>
29 #include <SeparatorView.h>
30 #include <String.h>
31 #include <StringView.h>
32 #include <TextControl.h>
33 #include <Window.h>
34 
35 #include <iostream>
36 
37 #include <stdio.h>
38 
39 using BPrivate::gMutableLocaleRoster;
40 
41 
42 #undef B_TRANSLATE_CONTEXT
43 #define B_TRANSLATE_CONTEXT "TimeFormatSettings"
44 
45 
46 class DateMenuItem: public BMenuItem {
47 public:
48 	DateMenuItem(const char* label, const char* code, BMenuField* field)
49 		:
50 		BMenuItem(label, _MenuMessage(code, field))
51 	{
52 		fIcuCode = code;
53 	}
54 
55 	const BString& ICUCode() const
56 	{
57 		return fIcuCode;
58 	}
59 
60 private:
61 	static BMessage* _MenuMessage(const char* format, BMenuField* field)
62 	{
63 		BMessage* msg = new BMessage(kMenuMessage);
64 		msg->AddPointer("dest", field);
65 		msg->AddString("format", format);
66 
67 		return msg;
68 	}
69 
70 private:
71 	BString			fIcuCode;
72 };
73 
74 
75 void
76 CreateDateMenu(BMenuField** field, bool longFormat = true)
77 {
78 	BMenu* menu = new BMenu("");
79 	*field = new BMenuField("", menu);
80 
81 	BPopUpMenu* dayMenu = new BPopUpMenu(B_TRANSLATE("Day"));
82 	// Not all available ICU settings are listed here. It's possible to add some
83 	// other things if you ever need.
84 	menu->AddItem(dayMenu);
85 		dayMenu->AddItem(new DateMenuItem(
86 			B_TRANSLATE("Day in month"), "d", *field));
87 		dayMenu->AddItem(new DateMenuItem(
88 			B_TRANSLATE("Day in month (2 digits)"), "dd", *field));
89 		/*
90 		dayMenu->AddItem(new DateMenuItem(B_TRANSLATE("Day in year"),
91 			"D", *field));
92 		dayMenu->AddItem(new DateMenuItem(B_TRANSLATE("Day in year (2 digits)"),
93 			 "DD", *field));
94 		dayMenu->AddItem(new DateMenuItem(B_TRANSLATE("Day in year (3 digits)"),
95 			"DDD", *field));
96 		*/
97 		dayMenu->AddItem(new DateMenuItem(
98 			B_TRANSLATE("Day of week"), "e", *field));
99 		// dayMenu->AddItem(new DateMenuItem("Day of week (short text)", "eee",
100 		//	*field));
101 		// dayMenu->AddItem(new DateMenuItem("Day of week (full text)", "eeee",
102 		//	*field));
103 		dayMenu->AddItem(new DateMenuItem(
104 			B_TRANSLATE("Day of week (short name)"), "E", *field));
105 		dayMenu->AddItem(new DateMenuItem(
106 			B_TRANSLATE("Day of week (name)"), "EEEE", *field));
107 		dayMenu->AddItem(new DateMenuItem(
108 			B_TRANSLATE("Day of week in month"), "F", *field));
109 		// dayMenu->AddItem(new DateMenuItem(
110 		//	B_TRANSLATE("julian day"), "g", *field));
111 		// dayMenu->AddItem(new BMenuItem("c", msg));
112 	BPopUpMenu* monthMenu = new BPopUpMenu(B_TRANSLATE("Month"));
113 	menu->AddItem(monthMenu);
114 		monthMenu->AddItem(new DateMenuItem(
115 			B_TRANSLATE("Month number"), "M", *field));
116 		monthMenu->AddItem(new DateMenuItem(
117 			B_TRANSLATE("Month number (2 digits)"), "MM", *field));
118 		monthMenu->AddItem(new DateMenuItem(
119 			B_TRANSLATE("Month name"), "MMMM", *field));
120 		// monthMenu->AddItem(new DateMenuItem("L", "L", *field));
121 	BPopUpMenu* yearMenu = new BPopUpMenu(B_TRANSLATE("Year"));
122 	menu->AddItem(yearMenu);
123 		// And here is some ICU kludge... sorry about that.
124 		if (longFormat)
125 			yearMenu->AddItem(new DateMenuItem(
126 				B_TRANSLATE("Year"), "y", *field));
127 		else {
128 			yearMenu->AddItem(new DateMenuItem(
129 				B_TRANSLATE("Year (4 digits)"), "yyyy", *field));
130 		}
131 		yearMenu->AddItem(new DateMenuItem(
132 			B_TRANSLATE("Year (2 digits)"), "yy", *field));
133 		// yearMenu->AddItem(new DateMenuItem("Y", "Y", *field));
134 		// yearMenu->AddItem(new DateMenuItem("u", "u", *field));
135 }
136 
137 
138 bool
139 IsSpecialDateChar(char charToTest)
140 {
141 	static const char* specials = "dDeEFgMLyYu";
142 	for (int i = 0; i < 11; i++)
143 		if (charToTest == specials[i])
144 			return true;
145 	return false;
146 }
147 
148 // #pragma mark -
149 
150 
151 FormatView::FormatView(const BLocale& locale)
152 	:
153 	BView("WindowsSettingsView", B_FRAME_EVENTS),
154 	fLocale(locale)
155 {
156 	SetLayout(new BGroupLayout(B_HORIZONTAL));
157 
158 	fLongDateExampleView = new BStringView("", "");
159 
160 	for (int i = 0; i < 4; i++) {
161 		CreateDateMenu(&fLongDateMenu[i]);
162 		fLongDateSeparator[i] = new BTextControl("", "", "",
163 			new BMessage(kSettingsContentsModified));
164 		fLongDateSeparator[i]->SetModificationMessage(
165 			new BMessage(kSettingsContentsModified));
166 	}
167 
168 	fShortDateExampleView = new BStringView("", "");
169 
170 	for (int i = 0; i < 3; i++) {
171 		CreateDateMenu(&fDateMenu[i], false);
172 	}
173 
174 	BPopUpMenu* menu = new BPopUpMenu(B_TRANSLATE("Separator"));
175 	menu->AddItem(new BMenuItem(B_TRANSLATE("None"),
176 		new BMessage(kSettingsContentsModified)));
177 	menu->AddItem(new BMenuItem(B_TRANSLATE("Space"),
178 		new BMessage(kSettingsContentsModified)));
179 	menu->AddItem(new BMenuItem("-", new BMessage(kSettingsContentsModified)));
180 	menu->AddItem(new BMenuItem("/", new BMessage(kSettingsContentsModified)));
181 	menu->AddItem(new BMenuItem("\\", new BMessage(kSettingsContentsModified)));
182 	menu->AddItem(new BMenuItem(".", new BMessage(kSettingsContentsModified)));
183 
184 	fSeparatorMenuField = new BMenuField(B_TRANSLATE("Separator:"), menu);
185 
186 	f24HrRadioButton = new BRadioButton("", B_TRANSLATE("24 hour"),
187 		new BMessage(kClockFormatChange));
188 
189 	f12HrRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"),
190 		new BMessage(kClockFormatChange));
191 
192 	fLocale.GetTimeFormat(fOriginalTimeFormat, false);
193 	fLocale.GetTimeFormat(fOriginalLongTimeFormat, true);
194 	if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
195 		f12HrRadioButton->SetValue(B_CONTROL_ON);
196 		fLocaleIs24Hr = false;
197 	} else {
198 		f24HrRadioButton->SetValue(B_CONTROL_ON);
199 		fLocaleIs24Hr = true;
200 	}
201 
202 	float spacing = be_control_look->DefaultItemSpacing();
203 
204 	fLongTimeExampleView = new BStringView("", "");
205 	fShortTimeExampleView = new BStringView("", "");
206 
207 	fNumberFormatExampleView = new BStringView("", "");
208 
209 	BTextControl* numberThousand = new BTextControl("",
210 		B_TRANSLATE("Thousand separator: "), "",
211 		new BMessage(kSettingsContentsModified));
212 	BTextControl* numberDecimal = new BTextControl("",
213 		B_TRANSLATE("Decimal separator: "),	"",
214 		new BMessage(kSettingsContentsModified));
215 	// TODO number of decimal digits (spinbox ?)
216 	BCheckBox* numberLeadingZero = new BCheckBox("", B_TRANSLATE("Leading 0"),
217 		new BMessage(kSettingsContentsModified));
218 	BTextControl* numberList = new BTextControl("",
219 		B_TRANSLATE("List separator: "), "",
220 		new BMessage(kSettingsContentsModified));
221 	// Unit system (US/Metric) (radio)
222 
223 	BTextControl* currencySymbol = new BTextControl("",
224 		B_TRANSLATE("Currency symbol:"), "",
225 		new BMessage(kSettingsContentsModified));
226 	menu = new BPopUpMenu(B_TRANSLATE("Negative marker"));
227 	menu->AddItem(new BMenuItem("-", new BMessage(kSettingsContentsModified)));
228 	menu->AddItem(new BMenuItem("()", new BMessage(kSettingsContentsModified)));
229 
230 	BMenuField* currencyNegative = new BMenuField(
231 		B_TRANSLATE("Negative marker:"), menu);
232 
233 	BTextControl* currencyDecimal = new BTextControl("",
234 		B_TRANSLATE("Decimal separator: "), "",
235 		new BMessage(kSettingsContentsModified));
236 	BCheckBox* currencyLeadingZero = new BCheckBox("",
237 		B_TRANSLATE("Leading 0"), new BMessage(kSettingsContentsModified));
238 
239 	BBox* formatBox = new BBox("Symbol position");
240 	formatBox->SetLabel(B_TRANSLATE("Symbol position"));
241 
242 	BRadioButton* beforeRadioButton = new BRadioButton("",
243 		B_TRANSLATE("Before"), new BMessage(kSettingsContentsModified));
244 
245 	BRadioButton* afterRadioButton = new BRadioButton("",
246 		B_TRANSLATE("After"), new BMessage(kSettingsContentsModified));
247 
248 	formatBox->AddChild(BGroupLayoutBuilder(B_VERTICAL)
249 		.Add(beforeRadioButton)
250 		.Add(afterRadioButton)
251 		.SetInsets(spacing, 0, spacing, 0));
252 
253 	_UpdateExamples();
254 	_ParseDateFormat();
255 
256 	fDateBox = new BBox(B_TRANSLATE("Date"));
257 	fTimeBox = new BBox(B_TRANSLATE("Time"));
258 	fNumbersBox = new BBox(B_TRANSLATE("Numbers"));
259 	fCurrencyBox = new BBox(B_TRANSLATE("Currency"));
260 
261 	fDateBox->SetLabel(B_TRANSLATE("Date"));
262 	fTimeBox->SetLabel(B_TRANSLATE("Time"));
263 	fNumbersBox->SetLabel(B_TRANSLATE("Numbers"));
264 	fCurrencyBox->SetLabel(B_TRANSLATE("Currency"));
265 
266 	fDateBox->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL)
267 		.AddGroup(B_VERTICAL, spacing / 2)
268 			.AddGroup(B_HORIZONTAL, spacing)
269 				.Add(new BStringView("", B_TRANSLATE("Long format:")))
270 				.Add(fLongDateExampleView)
271 				.AddGlue()
272 				.End()
273 			.AddGroup(B_HORIZONTAL, spacing)
274 				.Add(fLongDateMenu[0])
275 				.Add(fLongDateSeparator[0])
276 				.End()
277 			.AddGroup(B_HORIZONTAL, spacing)
278 				.Add(fLongDateMenu[1])
279 				.Add(fLongDateSeparator[1])
280 				.End()
281 			.AddGroup(B_HORIZONTAL, spacing)
282 				.Add(fLongDateMenu[2])
283 				.Add(fLongDateSeparator[2])
284 				.End()
285 			.AddGroup(B_HORIZONTAL, spacing)
286 				.Add(fLongDateMenu[3])
287 				.Add(fLongDateSeparator[3])
288 				.End()
289 			.AddGroup(B_HORIZONTAL, spacing)
290 				.Add(new BStringView("", B_TRANSLATE("Short format:")))
291 				.Add(fShortDateExampleView)
292 				.AddGlue()
293 				.End()
294 			.Add(fDateMenu[0])
295 			.Add(fDateMenu[1])
296 			.Add(fDateMenu[2])
297 			.End()
298 		.SetInsets(spacing, spacing, spacing, spacing));
299 
300 	fTimeBox->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing)
301 		.AddGroup(B_VERTICAL, spacing / 2)
302 			.AddGroup(B_HORIZONTAL, spacing)
303 				.Add(new BStringView("", B_TRANSLATE("Long format:")))
304 				.Add(fLongTimeExampleView)
305 				.AddGlue()
306 				.End()
307 			.AddGroup(B_HORIZONTAL, spacing)
308 				.Add(new BStringView("", B_TRANSLATE("Short format:")))
309 				.Add(fShortTimeExampleView)
310 				.AddGlue()
311 				.End()
312 			.AddGroup(B_HORIZONTAL, spacing)
313 				.Add(f24HrRadioButton)
314 				.Add(f12HrRadioButton)
315 				.AddGlue()
316 				.End()
317 			.End()
318 		.SetInsets(spacing, spacing, spacing, spacing));
319 
320 	fNumbersBox->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing)
321 		.AddGroup(B_VERTICAL, spacing / 2)
322 			.AddGroup(B_HORIZONTAL, spacing)
323 				.Add(new BStringView("", B_TRANSLATE("Example:")))
324 				.Add(fNumberFormatExampleView)
325 				.AddGlue()
326 				.End()
327 			.Add(numberThousand)
328 			.Add(numberDecimal)
329 			.Add(numberLeadingZero)
330 			.Add(numberList)
331 			.End()
332 		.SetInsets(spacing, spacing, spacing, spacing));
333 
334 	fCurrencyBox->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing)
335 		.AddGroup(B_VERTICAL, spacing / 2)
336 			.Add(currencySymbol)
337 			.Add(currencyNegative)
338 			.Add(currencyDecimal)
339 			.Add(currencyLeadingZero)
340 			.AddGroup(B_HORIZONTAL, spacing)
341 				.Add(formatBox)
342 				.AddGlue()
343 				.End()
344 			.End()
345 		.SetInsets(spacing, spacing, spacing, spacing));
346 
347 	AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing)
348 		.AddGroup(B_VERTICAL, spacing)
349 			.Add(fDateBox)
350 			.Add(fTimeBox)
351 			.AddGlue()
352 			.End()
353 		.AddGroup(B_VERTICAL, spacing)
354 			.Add(fNumbersBox)
355 			.Add(fCurrencyBox)
356 			.AddGlue()
357 			.End());
358 }
359 
360 
361 FormatView::~FormatView()
362 {
363 	gMutableLocaleRoster->SetDefaultLocale(fLocale);
364 }
365 
366 
367 void
368 FormatView::AttachedToWindow()
369 {
370 	f24HrRadioButton->SetTarget(this);
371 	f12HrRadioButton->SetTarget(this);
372 
373 	for (int j = 0; j < 4; j++) {
374 		for (int i = 0; i < fLongDateMenu[j]->Menu()->CountItems(); i++)
375 			fLongDateMenu[j]->Menu()->SubmenuAt(i)->SetTargetForItems(this);
376 		fLongDateSeparator[j]->SetTarget(this);
377 	}
378 
379 	for (int j = 0; j < 3; j++) {
380 		for (int i = 0; i < fDateMenu[j]->Menu()->CountItems(); i++)
381 			fDateMenu[j]->Menu()->SubmenuAt(i)->SetTargetForItems(this);
382 	}
383 
384 	fSeparatorMenuField->Menu()->SetTargetForItems(this);
385 }
386 
387 
388 void
389 FormatView::MessageReceived(BMessage* message)
390 {
391 	switch (message->what) {
392 		case kMenuMessage:
393 		{
394 			// Update one of the dropdown menus
395 			void* pointerFromMessage;
396 			message->FindPointer("dest", &pointerFromMessage);
397 			BMenuField* menuField
398 			= static_cast<BMenuField*>(pointerFromMessage);
399 			BString format;
400 			message->FindString("format", &format);
401 
402 			for (int i = 0; i < 4; i++) {
403 				if (fLongDateMenu[i]==menuField) {
404 					fLongDateString[i] = format;
405 					break;
406 				}
407 			}
408 
409 			for (int i = 0; i < 3; i++) {
410 				if (fDateMenu[i]==menuField) {
411 					fDateString[i] = format;
412 					break;
413 				}
414 			}
415 
416 			message->FindPointer("source", &pointerFromMessage);
417 			BMenuItem* menuItem = static_cast<BMenuItem*>(pointerFromMessage);
418 
419 			menuField->MenuItem()->SetLabel(menuItem->Label());
420 
421 			_UpdateLongDateFormatString();
422 		}
423 		// pass trough
424 		case kSettingsContentsModified:
425 			{
426 				int32 separator = 0;
427 				BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked();
428 				if (item) {
429 					separator = fSeparatorMenuField->Menu()->IndexOf(item);
430 					if (separator >= 0)
431 						// settings.SetTimeFormatSeparator(
432 						//	(FormatSeparator)separator);
433 						;
434 				}
435 
436 				// Make the notification message and send it to the tracker:
437 				BMessage notificationMessage;
438 				notificationMessage.AddInt32("TimeFormatSeparator", separator);
439 				notificationMessage.AddBool("24HrClock",
440 					f24HrRadioButton->Value() == 1);
441 
442 				_UpdateExamples();
443 
444 				Window()->PostMessage(kSettingsContentsModified);
445 				break;
446 			}
447 
448 		case kClockFormatChange:
449 		{
450 			BMessage newMessage(kMsgSettingsChanged);
451 
452 			BString timeFormat;
453 			timeFormat = fOriginalTimeFormat;
454 			if (f24HrRadioButton->Value() == 1) {
455 				if (!fLocaleIs24Hr) {
456 					timeFormat.ReplaceAll("h", "H");
457 					timeFormat.ReplaceAll("k", "K");
458 					timeFormat.RemoveAll(" a");
459 					timeFormat.RemoveAll("a");
460 				}
461 			} else {
462 				if (fLocaleIs24Hr && timeFormat.FindFirst("a") == B_ERROR) {
463 					timeFormat.ReplaceAll("K", "k");
464 					timeFormat.ReplaceAll("H", "h");
465 					timeFormat.Append(" a");
466 				}
467 			}
468 			fLocale.SetTimeFormat(timeFormat.String(), false);
469 			newMessage.AddString("shortTimeFormat", timeFormat);
470 
471 			timeFormat = fOriginalLongTimeFormat;
472 			if (f24HrRadioButton->Value() == 1) {
473 				if (!fLocaleIs24Hr) {
474 					timeFormat.ReplaceAll("h", "H");
475 					timeFormat.ReplaceAll("k", "K");
476 					timeFormat.RemoveAll(" a");
477 					timeFormat.RemoveAll("a");
478 				}
479 			} else {
480 				if (fLocaleIs24Hr && timeFormat.FindFirst("a") == B_ERROR) {
481 					timeFormat.ReplaceAll("K", "k");
482 					timeFormat.ReplaceAll("H", "h");
483 					timeFormat.Append(" a");
484 				}
485 			}
486 			fLocale.SetTimeFormat(timeFormat.String(), true);
487 			newMessage.AddString("longTimeFormat", timeFormat);
488 			_UpdateExamples();
489 			Window()->PostMessage(kSettingsContentsModified);
490 			be_app_messenger.SendMessage(&newMessage);
491 			break;
492 		}
493 
494 		default:
495 			BView::MessageReceived(message);
496 	}
497 }
498 
499 
500 void
501 FormatView::SetDefaults()
502 {
503 	/*
504 	TrackerSettings settings;
505 
506 	settings.SetTimeFormatSeparator(kSlashSeparator);
507 	settings.SetDateOrderFormat(kMDYFormat);
508 	settings.SetClockTo24Hr(false);
509 	*/
510 
511 	BLocale defaultLocale;
512 	be_locale_roster->GetDefaultLocale(&defaultLocale);
513 	fLocale = defaultLocale;
514 		// We work on a copy of the default country and set the changes when
515 		// closing the preflet
516 	_UpdateExamples();
517 	_SendNotices();
518 }
519 
520 
521 bool
522 FormatView::IsDefaultable() const
523 {
524 	/*
525 	TrackerSettings settings;
526 
527 	return settings.TimeFormatSeparator() != kSlashSeparator
528 		|| settings.DateOrderFormat() != kMDYFormat
529 		|| settings.ClockIs24Hr() != false;
530 	*/
531 	return true;
532 }
533 
534 
535 void
536 FormatView::Revert()
537 {
538 	/*
539 	TrackerSettings settings;
540 
541 	settings.SetTimeFormatSeparator(fSeparator);
542 	settings.SetDateOrderFormat(fFormat);
543 	settings.SetClockTo24Hr(f24HrClock);
544 	*/
545 
546 	// ShowCurrentSettings();
547 	_SendNotices();
548 }
549 
550 
551 void
552 FormatView::SetLocale(const BLocale& locale)
553 {
554 	fLocale = locale;
555 
556 	fLocale.GetTimeFormat(fOriginalTimeFormat, false);
557 	fLocale.GetTimeFormat(fOriginalLongTimeFormat, true);
558 
559 	if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
560 		f12HrRadioButton->SetValue(B_CONTROL_ON);
561 		fLocaleIs24Hr = false;
562 	} else {
563 		f24HrRadioButton->SetValue(B_CONTROL_ON);
564 		fLocaleIs24Hr = true;
565 	}
566 
567 	/*
568 	FormatSeparator separator = settings.TimeFormatSeparator();
569 
570 	if (separator >= kNoSeparator && separator < kSeparatorsEnd)
571 		fSeparatorMenuField->Menu()->ItemAt((int32)separator)->SetMarked(true);
572 	*/
573 	_UpdateExamples();
574 	_ParseDateFormat();
575 }
576 
577 
578 void
579 FormatView::RecordRevertSettings()
580 {
581 	/*
582 	f24HrClock = settings.ClockIs24Hr();
583 	fSeparator = settings.TimeFormatSeparator();
584 	fFormat = settings.DateOrderFormat();
585 	*/
586 }
587 
588 
589 // Return true if the Revert button should be enabled (ie some setting was
590 // changed)
591 bool
592 FormatView::IsRevertable() const
593 {
594 	FormatSeparator separator;
595 
596 	BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked();
597 	if (item) {
598 		int32 index = fSeparatorMenuField->Menu()->IndexOf(item);
599 		if (index >= 0)
600 			separator = (FormatSeparator)index;
601 		else
602 			return true;
603 	} else
604 		return true;
605 
606 	// TODO generate ICU string and compare to the initial one
607 	BString dateFormat ;
608 		// fYMDRadioButton->Value() ? kYMDFormat :
609 		//(fDMYRadioButton->Value() ? kDMYFormat : kMDYFormat);
610 
611 	return f24HrClock != (f24HrRadioButton->Value() > 0)
612 		|| separator != fSeparator
613 		|| dateFormat != fDateFormat;
614 }
615 
616 
617 void
618 FormatView::_UpdateExamples()
619 {
620 	time_t timeValue = (time_t)time(NULL);
621 	BString timeFormat;
622 
623 	fLocale.FormatDate(&timeFormat, timeValue, true);
624 	fLongDateExampleView->SetText(timeFormat);
625 
626 	fLocale.FormatDate(&timeFormat, timeValue, false);
627 	fShortDateExampleView->SetText(timeFormat);
628 
629 	fLocale.FormatTime(&timeFormat, timeValue, true);
630 	fLongTimeExampleView->SetText(timeFormat);
631 
632 	fLocale.FormatTime(&timeFormat, timeValue, false);
633 	fShortTimeExampleView->SetText(timeFormat);
634 
635 	status_t Error = fLocale.FormatNumber(&timeFormat, 1234.5678);
636 	if (Error == B_OK)
637 		fNumberFormatExampleView->SetText(timeFormat);
638 	else
639 		fNumberFormatExampleView->SetText("ERROR");
640 }
641 
642 
643 void
644 FormatView::_SendNotices()
645 {
646 	// Make the notification message and send it to the tracker:
647 	/*
648 	BMessage notificationMessage;
649 	notificationMessage.AddInt32("TimeFormatSeparator",
650 		(int32)settings.TimeFormatSeparator());
651 	notificationMessage.AddInt32("DateOrderFormat",
652 		(int32)settings.DateOrderFormat());
653 	notificationMessage.AddBool("24HrClock", settings.ClockIs24Hr());
654 	tracker->SendNotices(kDateFormatChanged, &notificationMessage);
655 	*/
656 }
657 
658 
659 //! Get the date format from ICU and set the date fields accordingly
660 void
661 FormatView::_ParseDateFormat()
662 {
663 	// TODO parse the short date too
664 	BString dateFormatString;
665 	fLocale.GetDateFormat(dateFormatString, true);
666 	const char* dateFormat = dateFormatString.String();
667 
668 printf("FV::_ParseDateFormat: df='%s'\n", dateFormat);
669 
670 	// Travel through the string and parse it
671 	const char* parsePointer = dateFormat;
672 	const char* fieldBegin = dateFormat;
673 
674 	for (int i = 0; i < 4; i++)
675 	{
676 		fieldBegin = parsePointer;
677 		while (*parsePointer == *(parsePointer + 1)) parsePointer++ ;
678 		parsePointer++;
679 		BString str;
680 		str.Append(fieldBegin, parsePointer - fieldBegin);
681 
682 		fLongDateString[i] = str;
683 
684 		BMenu* subMenu;
685 		bool isFound = false;
686 		for (int subMenuIndex = 0; subMenuIndex < 3; subMenuIndex++) {
687 			subMenu = fLongDateMenu[i]->Menu()->SubmenuAt(subMenuIndex);
688 			BMenuItem* item;
689 			for (int itemIndex = 0; (item = subMenu->ItemAt(itemIndex)) != NULL;
690 					itemIndex++) {
691 				if (static_cast<DateMenuItem*>(item)->ICUCode() == str) {
692 					item->SetMarked(true);
693 					fLongDateMenu[i]->MenuItem()->SetLabel(item->Label());
694 					isFound = true;
695 				} else
696 					item->SetMarked(false);
697 			}
698 		}
699 
700 		if (!isFound)
701 			fLongDateMenu[i]->MenuItem()->SetLabel(str.Append("*"));
702 
703 		fieldBegin = parsePointer;
704 		while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0'
705 				&& *(parsePointer - 1) >= 0) {
706 			if (*parsePointer == '\'') {
707 				parsePointer++;
708 				while (*parsePointer != '\'') parsePointer++;
709 			}
710 			parsePointer++;
711 		}
712 		str.Truncate(0);
713 		str.Append(fieldBegin, parsePointer - fieldBegin);
714 		fLongDateSeparator[i]->SetText(str);
715 	}
716 
717 	// Short date is a bit more tricky, we want to extract the separator
718 	fLocale.GetDateFormat(dateFormatString, false);
719 	dateFormat = dateFormatString.String();
720 
721 	// Travel trough the string and parse it
722 	parsePointer = dateFormat;
723 	fieldBegin = dateFormat;
724 
725 	for (int i = 0; i < 3; i++) {
726 		fieldBegin = parsePointer;
727 		while (*parsePointer == *(parsePointer + 1)) parsePointer++ ;
728 		parsePointer++;
729 		BString str;
730 		str.Append(fieldBegin, parsePointer - fieldBegin);
731 
732 		fLongDateString[i] = str;
733 
734 		BMenu* subMenu;
735 		bool isFound = false;
736 		for (int subMenuIndex = 0; subMenuIndex < 3; subMenuIndex++) {
737 			subMenu = fDateMenu[i]->Menu()->SubmenuAt(subMenuIndex);
738 			BMenuItem* item;
739 			for (int itemIndex = 0; (item = subMenu->ItemAt(itemIndex)) != NULL;
740 					itemIndex++) {
741 				if (static_cast<DateMenuItem*>(item)->ICUCode() == str) {
742 					item->SetMarked(true);
743 					fDateMenu[i]->MenuItem()->SetLabel(item->Label());
744 					isFound = true;
745 				} else
746 					item->SetMarked(false);
747 			}
748 		}
749 
750 		if (!isFound) {
751 			fDateMenu[i]->MenuItem()->SetLabel(
752 				str.Append(B_TRANSLATE(" (unknown format)")));
753 		}
754 
755 		fieldBegin = parsePointer;
756 		while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0'
757 				&& *(parsePointer - 1) >= 0) {
758 			if (*parsePointer == '\'') {
759 				parsePointer++;
760 				while (*parsePointer != '\'') parsePointer++;
761 			}
762 			parsePointer++;
763 		}
764 		if (parsePointer - fieldBegin > 0) {
765 			str.Truncate(0);
766 			str.Append(fieldBegin, parsePointer - fieldBegin);
767 			fSeparatorMenuField->MenuItem()->SetLabel(str);
768 		}
769 	}
770 }
771 
772 
773 void
774 FormatView::_UpdateLongDateFormatString()
775 {
776 	BString newDateFormat;
777 
778 	for (int i = 0; i < 4; i++) {
779 		newDateFormat.Append(fLongDateString[i]);
780 		newDateFormat.Append(fLongDateSeparator[i]->Text());
781 	}
782 
783 	// TODO save this in the settings preflet and make the roster load it back
784 	fLocale.SetDateFormat(newDateFormat.String());
785 
786 	newDateFormat.Truncate(0);
787 
788 	newDateFormat.Append(fDateString[0]);
789 	newDateFormat.Append(fSeparatorMenuField->MenuItem()->Label());
790 	newDateFormat.Append(fDateString[1]);
791 	newDateFormat.Append(fSeparatorMenuField->MenuItem()->Label());
792 	newDateFormat.Append(fDateString[2]);
793 
794 	// TODO save this in the settings preflet and make the roster load it back
795 	fLocale.SetDateFormat(newDateFormat.String(), false);
796 }
797