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