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