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 <stdlib.h> 10 11 #include <Alert.h> 12 #include <Application.h> 13 #include <Catalog.h> 14 #include <CheckBox.h> 15 #include <ControlLook.h> 16 #include <DateFormat.h> 17 #include <GridLayout.h> 18 #include <GridLayoutBuilder.h> 19 #include <GroupLayout.h> 20 #include <GroupLayoutBuilder.h> 21 #include <LayoutBuilder.h> 22 #include <Locale.h> 23 #include <MutableLocaleRoster.h> 24 #include <Message.h> 25 #include <Menu.h> 26 #include <MenuField.h> 27 #include <MenuItem.h> 28 #include <NumberFormat.h> 29 #include <PopUpMenu.h> 30 #include <RadioButton.h> 31 #include <ScrollView.h> 32 #include <ScrollBar.h> 33 #include <SeparatorView.h> 34 #include <SpaceLayoutItem.h> 35 #include <String.h> 36 #include <StringView.h> 37 #include <TextControl.h> 38 #include <TimeFormat.h> 39 #include <Window.h> 40 41 #include "LocalePreflet.h" 42 43 44 using BPrivate::MutableLocaleRoster; 45 46 47 #undef B_TRANSLATION_CONTEXT 48 #define B_TRANSLATION_CONTEXT "TimeFormatSettings" 49 50 51 // #pragma mark - 52 53 54 FormatSettingsView::FormatSettingsView() 55 : 56 BView("WindowsSettingsView", B_FRAME_EVENTS) 57 { 58 fUseLanguageStringsCheckBox = new BCheckBox( 59 B_TRANSLATE("Use month/day-names from preferred language"), 60 new BMessage(kStringsLanguageChange)); 61 62 fFilesystemTranslationCheckbox = new BCheckBox("filesystemTranslation", 63 B_TRANSLATE("Translate application and folder names"), 64 new BMessage(kMsgFilesystemTranslationChanged)); 65 fFilesystemTranslationCheckbox->SetValue( 66 BLocaleRoster::Default()->IsFilesystemTranslationPreferred()); 67 68 BStringView* fullDateLabel 69 = new BStringView("", B_TRANSLATE("Full format:")); 70 fullDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 71 B_ALIGN_VERTICAL_UNSET)); 72 BStringView* longDateLabel 73 = new BStringView("", B_TRANSLATE("Long format:")); 74 longDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 75 B_ALIGN_VERTICAL_UNSET)); 76 BStringView* mediumDateLabel 77 = new BStringView("", B_TRANSLATE("Medium format:")); 78 mediumDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 79 B_ALIGN_VERTICAL_UNSET)); 80 BStringView* shortDateLabel 81 = new BStringView("", B_TRANSLATE("Short format:")); 82 shortDateLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 83 B_ALIGN_VERTICAL_UNSET)); 84 85 fFullDateExampleView = new BStringView("", ""); 86 fFullDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 87 B_ALIGN_VERTICAL_UNSET)); 88 fLongDateExampleView = new BStringView("", ""); 89 fLongDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 90 B_ALIGN_VERTICAL_UNSET)); 91 fMediumDateExampleView = new BStringView("", ""); 92 fMediumDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 93 B_ALIGN_VERTICAL_UNSET)); 94 fShortDateExampleView = new BStringView("", ""); 95 fShortDateExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 96 B_ALIGN_VERTICAL_UNSET)); 97 98 f24HourRadioButton = new BRadioButton("", B_TRANSLATE("24 hour"), 99 new BMessage(kClockFormatChange)); 100 f12HourRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"), 101 new BMessage(kClockFormatChange)); 102 103 float spacing = be_control_look->DefaultItemSpacing(); 104 105 BStringView* fullTimeLabel 106 = new BStringView("", B_TRANSLATE("Full format:")); 107 fullTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 108 B_ALIGN_VERTICAL_UNSET)); 109 BStringView* longTimeLabel 110 = new BStringView("", B_TRANSLATE("Long format:")); 111 longTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 112 B_ALIGN_VERTICAL_UNSET)); 113 BStringView* mediumTimeLabel 114 = new BStringView("", B_TRANSLATE("Medium format:")); 115 mediumTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 116 B_ALIGN_VERTICAL_UNSET)); 117 BStringView* shortTimeLabel 118 = new BStringView("", B_TRANSLATE("Short format:")); 119 shortTimeLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 120 B_ALIGN_VERTICAL_UNSET)); 121 122 fFullTimeExampleView = new BStringView("", ""); 123 fFullTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 124 B_ALIGN_VERTICAL_UNSET)); 125 fLongTimeExampleView = new BStringView("", ""); 126 fLongTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 127 B_ALIGN_VERTICAL_UNSET)); 128 fMediumTimeExampleView = new BStringView("", ""); 129 fMediumTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 130 B_ALIGN_VERTICAL_UNSET)); 131 fShortTimeExampleView = new BStringView("", ""); 132 fShortTimeExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 133 B_ALIGN_VERTICAL_UNSET)); 134 135 BStringView* positiveNumberLabel 136 = new BStringView("", B_TRANSLATE("Positive:")); 137 positiveNumberLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 138 B_ALIGN_VERTICAL_UNSET)); 139 BStringView* negativeNumberLabel 140 = new BStringView("", B_TRANSLATE("Negative:")); 141 negativeNumberLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 142 B_ALIGN_VERTICAL_UNSET)); 143 144 fPositiveNumberExampleView = new BStringView("", ""); 145 fPositiveNumberExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, 146 B_ALIGN_VERTICAL_UNSET)); 147 fNegativeNumberExampleView = new BStringView("", ""); 148 fNegativeNumberExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, 149 B_ALIGN_VERTICAL_UNSET)); 150 151 BStringView* positiveMonetaryLabel 152 = new BStringView("", B_TRANSLATE("Positive:")); 153 positiveMonetaryLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 154 B_ALIGN_VERTICAL_UNSET)); 155 BStringView* negativeMonetaryLabel 156 = new BStringView("", B_TRANSLATE("Negative:")); 157 negativeMonetaryLabel->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 158 B_ALIGN_VERTICAL_UNSET)); 159 160 fPositiveMonetaryExampleView = new BStringView("", ""); 161 fPositiveMonetaryExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, 162 B_ALIGN_VERTICAL_UNSET)); 163 fNegativeMonetaryExampleView = new BStringView("", ""); 164 fNegativeMonetaryExampleView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, 165 B_ALIGN_VERTICAL_UNSET)); 166 167 Refresh(true); 168 169 fDateBox = new BBox(B_TRANSLATE("Date")); 170 fTimeBox = new BBox(B_TRANSLATE("Time")); 171 fNumberBox = new BBox(B_TRANSLATE("Numbers")); 172 fMonetaryBox = new BBox(B_TRANSLATE("Currency")); 173 174 fDateBox->SetLabel(B_TRANSLATE("Date")); 175 fTimeBox->SetLabel(B_TRANSLATE("Time")); 176 fNumberBox->SetLabel(B_TRANSLATE("Numbers")); 177 fMonetaryBox->SetLabel(B_TRANSLATE("Currency")); 178 179 fDateBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) 180 .SetInsets(spacing, spacing, spacing, spacing) 181 .Add(fullDateLabel, 0, 0) 182 .Add(fFullDateExampleView, 1, 0) 183 .Add(BSpaceLayoutItem::CreateGlue(), 2, 0) 184 .Add(longDateLabel, 0, 1) 185 .Add(fLongDateExampleView, 1, 1) 186 .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) 187 .Add(mediumDateLabel, 0, 2) 188 .Add(fMediumDateExampleView, 1, 2) 189 .Add(BSpaceLayoutItem::CreateGlue(), 2, 2) 190 .Add(shortDateLabel, 0, 3) 191 .Add(fShortDateExampleView, 1, 3) 192 .Add(BSpaceLayoutItem::CreateGlue(), 2, 3) 193 .View()); 194 195 fTimeBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) 196 .SetInsets(spacing, spacing, spacing, spacing) 197 .AddGroup(B_HORIZONTAL, spacing, 0, 0, 2) 198 .Add(f24HourRadioButton, 0) 199 .Add(f12HourRadioButton, 0) 200 .AddGlue() 201 .End() 202 .Add(fullTimeLabel, 0, 1) 203 .Add(fFullTimeExampleView, 1, 1) 204 .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) 205 .Add(longTimeLabel, 0, 2) 206 .Add(fLongTimeExampleView, 1, 2) 207 .Add(BSpaceLayoutItem::CreateGlue(), 2, 2) 208 .Add(mediumTimeLabel, 0, 3) 209 .Add(fMediumTimeExampleView, 1, 3) 210 .Add(BSpaceLayoutItem::CreateGlue(), 2, 3) 211 .Add(shortTimeLabel, 0, 4) 212 .Add(fShortTimeExampleView, 1, 4) 213 .Add(BSpaceLayoutItem::CreateGlue(), 2, 4) 214 .View()); 215 216 fNumberBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) 217 .SetInsets(spacing, spacing, spacing, spacing) 218 .Add(positiveNumberLabel, 0, 0) 219 .Add(fPositiveNumberExampleView, 1, 0) 220 .Add(BSpaceLayoutItem::CreateGlue(), 2, 0) 221 .Add(negativeNumberLabel, 0, 1) 222 .Add(fNegativeNumberExampleView, 1, 1) 223 .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) 224 .View()); 225 226 fMonetaryBox->AddChild(BLayoutBuilder::Grid<>(spacing, spacing / 2) 227 .SetInsets(spacing, spacing, spacing, spacing) 228 .Add(positiveMonetaryLabel, 0, 0) 229 .Add(fPositiveMonetaryExampleView, 1, 0) 230 .Add(BSpaceLayoutItem::CreateGlue(), 2, 0) 231 .Add(negativeMonetaryLabel, 0, 1) 232 .Add(fNegativeMonetaryExampleView, 1, 1) 233 .Add(BSpaceLayoutItem::CreateGlue(), 2, 1) 234 .View()); 235 236 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 237 238 BLayoutBuilder::Group<>(this, B_VERTICAL) 239 .Add(fFilesystemTranslationCheckbox) 240 .Add(fUseLanguageStringsCheckBox) 241 .Add(fDateBox) 242 .Add(fTimeBox) 243 .AddGroup(B_HORIZONTAL, spacing) 244 .Add(fNumberBox) 245 .Add(fMonetaryBox) 246 .End() 247 .AddGlue(); 248 } 249 250 251 FormatSettingsView::~FormatSettingsView() 252 { 253 } 254 255 256 void 257 FormatSettingsView::AttachedToWindow() 258 { 259 fFilesystemTranslationCheckbox->SetTarget(Window()); 260 fUseLanguageStringsCheckBox->SetTarget(this); 261 f24HourRadioButton->SetTarget(this); 262 f12HourRadioButton->SetTarget(this); 263 } 264 265 266 void 267 FormatSettingsView::MessageReceived(BMessage* message) 268 { 269 switch (message->what) { 270 case B_LOCALE_CHANGED: 271 { 272 // Time updated 12/24 hour clock 273 BFormattingConventions conventions; 274 BLocale::Default()->GetFormattingConventions(&conventions); 275 if (conventions.Use24HourClock()) 276 f24HourRadioButton->SetValue(B_CONTROL_ON); 277 else 278 f12HourRadioButton->SetValue(B_CONTROL_ON); 279 280 _UpdateExamples(); 281 Window()->PostMessage(kMsgSettingsChanged); 282 break; 283 } 284 285 case kClockFormatChange: 286 { 287 BFormattingConventions conventions; 288 BLocale::Default()->GetFormattingConventions(&conventions); 289 conventions.SetExplicitUse24HourClock( 290 f24HourRadioButton->Value() == B_CONTROL_ON); 291 MutableLocaleRoster::Default()->SetDefaultFormattingConventions( 292 conventions); 293 294 _UpdateExamples(); 295 Window()->PostMessage(kMsgSettingsChanged); 296 break; 297 } 298 299 case kStringsLanguageChange: 300 { 301 BFormattingConventions conventions; 302 BLocale::Default()->GetFormattingConventions(&conventions); 303 conventions.SetUseStringsFromPreferredLanguage( 304 fUseLanguageStringsCheckBox->Value() ? true : false); 305 MutableLocaleRoster::Default()->SetDefaultFormattingConventions( 306 conventions); 307 308 _UpdateExamples(); 309 310 Window()->PostMessage(kMsgSettingsChanged); 311 break; 312 } 313 314 default: 315 BView::MessageReceived(message); 316 } 317 } 318 319 320 void 321 FormatSettingsView::Revert() 322 { 323 MutableLocaleRoster::Default()->SetDefaultFormattingConventions( 324 fInitialConventions); 325 326 fFilesystemTranslationCheckbox->SetValue(fInitialTranslateNames); 327 328 _UpdateExamples(); 329 } 330 331 332 void 333 FormatSettingsView::Refresh(bool setInitial) 334 { 335 BFormattingConventions conventions; 336 BLocale::Default()->GetFormattingConventions(&conventions); 337 if (setInitial) { 338 fInitialConventions = conventions; 339 fInitialTranslateNames 340 = BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); 341 } 342 343 if (!conventions.Use24HourClock()) { 344 f12HourRadioButton->SetValue(B_CONTROL_ON); 345 fLocaleIs24Hour = false; 346 } else { 347 f24HourRadioButton->SetValue(B_CONTROL_ON); 348 fLocaleIs24Hour = true; 349 } 350 351 fUseLanguageStringsCheckBox->SetValue( 352 conventions.UseStringsFromPreferredLanguage() 353 ? B_CONTROL_ON : B_CONTROL_OFF); 354 355 _UpdateExamples(); 356 } 357 358 359 // Return true if the Revert button should be enabled (i.e. something has been 360 // changed) 361 bool 362 FormatSettingsView::IsReversible() const 363 { 364 BFormattingConventions conventions; 365 BLocale::Default()->GetFormattingConventions(&conventions); 366 367 return (conventions != fInitialConventions) 368 || (fFilesystemTranslationCheckbox->Value() != fInitialTranslateNames); 369 } 370 371 372 void 373 FormatSettingsView::_UpdateExamples() 374 { 375 time_t timeValue = (time_t)time(NULL); 376 BString result; 377 378 // Do NOT make these class members. We do want to recreate it everytime, as 379 // to get the updated settings from the locale roster. 380 BDateFormat dateFormat; 381 BNumberFormat numberFormat; 382 BString errorString = B_TRANSLATE("ERROR"); 383 BTimeFormat timeFormat; 384 385 dateFormat.Format(result, timeValue, B_FULL_DATE_FORMAT); 386 fFullDateExampleView->SetText(result); 387 388 dateFormat.Format(result, timeValue, B_LONG_DATE_FORMAT); 389 fLongDateExampleView->SetText(result); 390 391 dateFormat.Format(result, timeValue, B_MEDIUM_DATE_FORMAT); 392 fMediumDateExampleView->SetText(result); 393 394 dateFormat.Format(result, timeValue, B_SHORT_DATE_FORMAT); 395 fShortDateExampleView->SetText(result); 396 397 timeFormat.Format(result, timeValue, B_FULL_TIME_FORMAT); 398 fFullTimeExampleView->SetText(result); 399 400 timeFormat.Format(result, timeValue, B_LONG_TIME_FORMAT); 401 fLongTimeExampleView->SetText(result); 402 403 timeFormat.Format(result, timeValue, B_MEDIUM_TIME_FORMAT); 404 fMediumTimeExampleView->SetText(result); 405 406 timeFormat.Format(result, timeValue, B_SHORT_TIME_FORMAT); 407 fShortTimeExampleView->SetText(result); 408 409 status_t status = numberFormat.Format(result, 1234.56); 410 if (status == B_OK) 411 fPositiveNumberExampleView->SetText(result); 412 else 413 fPositiveNumberExampleView->SetText(errorString); 414 415 status = numberFormat.Format(result, -1234.56); 416 if (status == B_OK) 417 fNegativeNumberExampleView->SetText(result); 418 else 419 fNegativeNumberExampleView->SetText(errorString); 420 421 status = numberFormat.FormatMonetary(result, 1234.56); 422 if (status == B_OK) 423 fPositiveMonetaryExampleView->SetText(result); 424 else 425 fPositiveMonetaryExampleView->SetText(errorString); 426 427 status = numberFormat.FormatMonetary(result, -1234.56); 428 if (status == B_OK) 429 fNegativeMonetaryExampleView->SetText(result); 430 else 431 fNegativeMonetaryExampleView->SetText(errorString); 432 } 433