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 } 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 fLocale = *be_locale; 507 // We work on a copy of the default country and set the changes when 508 // closing the preflet 509 _UpdateExamples(); 510 _SendNotices(); 511 } 512 513 514 bool 515 FormatView::IsDefaultable() const 516 { 517 /* 518 TrackerSettings settings; 519 520 return settings.TimeFormatSeparator() != kSlashSeparator 521 || settings.DateOrderFormat() != kMDYFormat 522 || settings.ClockIs24Hr() != false; 523 */ 524 return true; 525 } 526 527 528 void 529 FormatView::Revert() 530 { 531 /* 532 TrackerSettings settings; 533 534 settings.SetTimeFormatSeparator(fSeparator); 535 settings.SetDateOrderFormat(fFormat); 536 settings.SetClockTo24Hr(f24HrClock); 537 */ 538 539 // ShowCurrentSettings(); 540 _SendNotices(); 541 } 542 543 544 void 545 FormatView::SetLocale(const BLocale& locale) 546 { 547 fLocale = locale; 548 549 fLocale.GetTimeFormat(fOriginalTimeFormat, false); 550 fLocale.GetTimeFormat(fOriginalLongTimeFormat, true); 551 552 if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) { 553 f12HrRadioButton->SetValue(B_CONTROL_ON); 554 fLocaleIs24Hr = false; 555 } else { 556 f24HrRadioButton->SetValue(B_CONTROL_ON); 557 fLocaleIs24Hr = true; 558 } 559 560 /* 561 FormatSeparator separator = settings.TimeFormatSeparator(); 562 563 if (separator >= kNoSeparator && separator < kSeparatorsEnd) 564 fSeparatorMenuField->Menu()->ItemAt((int32)separator)->SetMarked(true); 565 */ 566 567 _UpdateExamples(); 568 _ParseDateFormat(); 569 _ParseCurrencyFormat(); 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 void 655 FormatView::_ParseCurrencyFormat() 656 { 657 BString currencySample; 658 int* fieldPos = NULL; 659 int fieldCount; 660 BNumberElement* fieldID = NULL; 661 if (fLocale.FormatMonetary(¤cySample, fieldPos, fieldID, fieldCount, 662 -1234.56) != B_OK) { 663 fMonetaryView->SetText("ERROR"); 664 return; 665 } 666 667 fMonetaryView->SetText(currencySample); 668 669 for (int i = 0; i < fieldCount; i++) { 670 BString currentSymbol; 671 currentSymbol.AppendChars(currencySample.CharAt(fieldPos[i]&0xFFFF), 672 (fieldPos[i]>>16) - (fieldPos[i]&0xFFFF)); 673 switch (fieldID[i]) { 674 case B_NUMBER_ELEMENT_CURRENCY: 675 fCurrencySymbolView->SetText(currentSymbol); 676 if (i > fieldCount / 2) 677 fCurrencySymbolAfter->SetValue(1); 678 else 679 fCurrencySymbolBefore->SetValue(1); 680 break; 681 default: 682 break; 683 } 684 } 685 686 free(fieldPos); 687 free(fieldID); 688 } 689 690 691 //! Get the date format from ICU and set the date fields accordingly 692 void 693 FormatView::_ParseDateFormat() 694 { 695 // TODO parse the short date too 696 BString dateFormatString; 697 fLocale.GetDateFormat(dateFormatString, true); 698 const char* dateFormat = dateFormatString.String(); 699 700 // Travel through the string and parse it 701 const char* parsePointer = dateFormat; 702 const char* fieldBegin = dateFormat; 703 704 for (int i = 0; i < 4; i++) 705 { 706 fieldBegin = parsePointer; 707 while (*parsePointer == *(parsePointer + 1)) parsePointer++ ; 708 parsePointer++; 709 BString str; 710 str.Append(fieldBegin, parsePointer - fieldBegin); 711 712 fLongDateString[i] = str; 713 714 BMenu* subMenu; 715 bool isFound = false; 716 for (int subMenuIndex = 0; subMenuIndex < 3; subMenuIndex++) { 717 subMenu = fLongDateMenu[i]->Menu()->SubmenuAt(subMenuIndex); 718 BMenuItem* item; 719 for (int itemIndex = 0; (item = subMenu->ItemAt(itemIndex)) != NULL; 720 itemIndex++) { 721 if (static_cast<DateMenuItem*>(item)->ICUCode() == str) { 722 item->SetMarked(true); 723 fLongDateMenu[i]->MenuItem()->SetLabel(item->Label()); 724 isFound = true; 725 } else 726 item->SetMarked(false); 727 } 728 } 729 730 if (!isFound) 731 fLongDateMenu[i]->MenuItem()->SetLabel(str.Append("*")); 732 733 fieldBegin = parsePointer; 734 while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0' 735 && *(parsePointer - 1) >= 0) { 736 if (*parsePointer == '\'') { 737 parsePointer++; 738 while (*parsePointer != '\'') parsePointer++; 739 } 740 parsePointer++; 741 } 742 str.Truncate(0); 743 str.Append(fieldBegin, parsePointer - fieldBegin); 744 fLongDateSeparator[i]->SetText(str); 745 } 746 747 // Short date is a bit more tricky, we want to extract the separator 748 fLocale.GetDateFormat(dateFormatString, false); 749 dateFormat = dateFormatString.String(); 750 751 // Travel trough the string and parse it 752 parsePointer = dateFormat; 753 fieldBegin = dateFormat; 754 755 for (int i = 0; i < 3; i++) { 756 fieldBegin = parsePointer; 757 while (*parsePointer == *(parsePointer + 1)) parsePointer++ ; 758 parsePointer++; 759 BString str; 760 str.Append(fieldBegin, parsePointer - fieldBegin); 761 762 fLongDateString[i] = str; 763 764 BMenu* subMenu; 765 bool isFound = false; 766 for (int subMenuIndex = 0; subMenuIndex < 3; subMenuIndex++) { 767 subMenu = fDateMenu[i]->Menu()->SubmenuAt(subMenuIndex); 768 BMenuItem* item; 769 for (int itemIndex = 0; (item = subMenu->ItemAt(itemIndex)) != NULL; 770 itemIndex++) { 771 if (static_cast<DateMenuItem*>(item)->ICUCode() == str) { 772 item->SetMarked(true); 773 fDateMenu[i]->MenuItem()->SetLabel(item->Label()); 774 isFound = true; 775 } else 776 item->SetMarked(false); 777 } 778 } 779 780 if (!isFound) { 781 fDateMenu[i]->MenuItem()->SetLabel( 782 str.Append(B_TRANSLATE(" (unknown format)"))); 783 } 784 785 fieldBegin = parsePointer; 786 while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0' 787 && *(parsePointer - 1) >= 0) { 788 if (*parsePointer == '\'') { 789 parsePointer++; 790 while (*parsePointer != '\'') parsePointer++; 791 } 792 parsePointer++; 793 } 794 if (parsePointer - fieldBegin > 0) { 795 str.Truncate(0); 796 str.Append(fieldBegin, parsePointer - fieldBegin); 797 fSeparatorMenuField->MenuItem()->SetLabel(str); 798 } 799 } 800 } 801 802 803 void 804 FormatView::_UpdateLongDateFormatString() 805 { 806 BString newDateFormat; 807 808 for (int i = 0; i < 4; i++) { 809 newDateFormat.Append(fLongDateString[i]); 810 newDateFormat.Append(fLongDateSeparator[i]->Text()); 811 } 812 813 // TODO save this in the settings preflet and make the roster load it back 814 fLocale.SetDateFormat(newDateFormat.String()); 815 816 newDateFormat.Truncate(0); 817 818 newDateFormat.Append(fDateString[0]); 819 newDateFormat.Append(fSeparatorMenuField->MenuItem()->Label()); 820 newDateFormat.Append(fDateString[1]); 821 newDateFormat.Append(fSeparatorMenuField->MenuItem()->Label()); 822 newDateFormat.Append(fDateString[2]); 823 824 // TODO save this in the settings preflet and make the roster load it back 825 fLocale.SetDateFormat(newDateFormat.String(), false); 826 } 827