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, ¬ificationMessage); 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