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