1 /* 2 * Copyright 2010-2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Alexander von Gluck <kallisti5@unixzen.com> 8 * John Scipione <jscipione@gmail.com> 9 * Ryan Leavengood <leavengood@gmail.com> 10 */ 11 12 13 #include "LookAndFeelSettingsView.h" 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 18 #include <Alert.h> 19 #include <Alignment.h> 20 #include <AppFileInfo.h> 21 #include <Box.h> 22 #include <Button.h> 23 #include <Catalog.h> 24 #include <CheckBox.h> 25 #include <File.h> 26 #include <InterfaceDefs.h> 27 #include <InterfacePrivate.h> 28 #include <LayoutBuilder.h> 29 #include <Locale.h> 30 #include <MenuField.h> 31 #include <MenuItem.h> 32 #include <Path.h> 33 #include <PathFinder.h> 34 #include <PopUpMenu.h> 35 #include <ScrollBar.h> 36 #include <StringView.h> 37 #include <Size.h> 38 #include <Slider.h> 39 #include <SpaceLayoutItem.h> 40 #include <StringView.h> 41 #include <TextView.h> 42 43 #include "APRWindow.h" 44 #include "FakeScrollBar.h" 45 46 47 #undef B_TRANSLATION_CONTEXT 48 #define B_TRANSLATION_CONTEXT "DecorSettingsView" 49 // This was not renamed to keep from breaking translations 50 51 52 static const int32 kMsgSetDecor = 'deco'; 53 static const int32 kMsgDecorInfo = 'idec'; 54 55 static const int32 kMsgSetControlLook = 'ctlk'; 56 static const int32 kMsgControlLookInfo = 'iclk'; 57 58 static const int32 kMsgDoubleScrollBarArrows = 'dsba'; 59 60 static const int32 kMsgArrowStyleSingle = 'mass'; 61 static const int32 kMsgArrowStyleDouble = 'masd'; 62 63 static const int32 kMsgKnobStyleNone = 'mksn'; 64 static const int32 kMsgKnobStyleDots = 'mksd'; 65 static const int32 kMsgKnobStyleLines = 'mksl'; 66 67 static const bool kDefaultDoubleScrollBarArrowsSetting = false; 68 69 70 // #pragma mark - 71 72 73 LookAndFeelSettingsView::LookAndFeelSettingsView(const char* name) 74 : 75 BView(name, 0), 76 fDecorInfoButton(NULL), 77 fDecorMenuField(NULL), 78 fDecorMenu(NULL), 79 fControlLookInfoButton(NULL), 80 fControlLookMenuField(NULL), 81 fControlLookMenu(NULL) 82 { 83 // Decorator menu 84 _BuildDecorMenu(); 85 fDecorMenuField = new BMenuField("decorator", 86 B_TRANSLATE("Decorator:"), fDecorMenu); 87 88 fDecorInfoButton = new BButton(B_TRANSLATE("About"), 89 new BMessage(kMsgDecorInfo)); 90 91 // ControlLook menu 92 _BuildControlLookMenu(); 93 fControlLookMenuField = new BMenuField("controllook", 94 B_TRANSLATE("ControlLook:"), fControlLookMenu); 95 fControlLookMenuField->SetToolTip(B_TRANSLATE("No effect on running applications")); 96 97 fControlLookInfoButton = new BButton(B_TRANSLATE("About"), 98 new BMessage(kMsgControlLookInfo)); 99 100 // scroll bar arrow style 101 BBox* arrowStyleBox = new BBox("arrow style"); 102 arrowStyleBox->SetLabel(B_TRANSLATE("Arrow style")); 103 104 fSavedDoubleArrowsValue = _DoubleScrollBarArrows(); 105 106 fArrowStyleSingle = new FakeScrollBar(true, false, 107 new BMessage(kMsgArrowStyleSingle)); 108 fArrowStyleDouble = new FakeScrollBar(true, true, 109 new BMessage(kMsgArrowStyleDouble)); 110 111 BView* arrowStyleView; 112 arrowStyleView = BLayoutBuilder::Group<>() 113 .AddGroup(B_VERTICAL, 1) 114 .Add(new BStringView("single", B_TRANSLATE("Single:"))) 115 .Add(fArrowStyleSingle) 116 .AddStrut(B_USE_DEFAULT_SPACING) 117 .Add(new BStringView("double", B_TRANSLATE("Double:"))) 118 .Add(fArrowStyleDouble) 119 .SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 120 B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) 121 .End() 122 .View(); 123 arrowStyleBox->AddChild(arrowStyleView); 124 arrowStyleBox->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 125 B_ALIGN_VERTICAL_CENTER)); 126 arrowStyleBox->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 127 128 BStringView* scrollBarLabel 129 = new BStringView("scroll bar", B_TRANSLATE("Scroll bar:")); 130 scrollBarLabel->SetExplicitAlignment( 131 BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP)); 132 133 // control layout 134 BLayoutBuilder::Grid<>(this, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) 135 .Add(fDecorMenuField->CreateLabelLayoutItem(), 0, 0) 136 .Add(fDecorMenuField->CreateMenuBarLayoutItem(), 1, 0) 137 .Add(fDecorInfoButton, 2, 0) 138 .Add(fControlLookMenuField->CreateLabelLayoutItem(), 0, 1) 139 .Add(fControlLookMenuField->CreateMenuBarLayoutItem(), 1, 1) 140 .Add(fControlLookInfoButton, 2, 1) 141 .Add(scrollBarLabel, 0, 2) 142 .Add(arrowStyleBox, 1, 2) 143 .AddGlue(0, 3) 144 .SetInsets(B_USE_WINDOW_SPACING); 145 146 // TODO : Decorator Preview Image? 147 } 148 149 150 LookAndFeelSettingsView::~LookAndFeelSettingsView() 151 { 152 } 153 154 155 void 156 LookAndFeelSettingsView::AttachedToWindow() 157 { 158 AdoptParentColors(); 159 160 if (Parent() == NULL) 161 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 162 163 fDecorMenu->SetTargetForItems(this); 164 fDecorInfoButton->SetTarget(this); 165 fControlLookMenu->SetTargetForItems(this); 166 fControlLookInfoButton->SetTarget(this); 167 fArrowStyleSingle->SetTarget(this); 168 fArrowStyleDouble->SetTarget(this); 169 170 if (fSavedDoubleArrowsValue) 171 fArrowStyleDouble->SetValue(B_CONTROL_ON); 172 else 173 fArrowStyleSingle->SetValue(B_CONTROL_ON); 174 } 175 176 177 void 178 LookAndFeelSettingsView::MessageReceived(BMessage *msg) 179 { 180 switch (msg->what) { 181 case kMsgSetDecor: 182 { 183 BString newDecor; 184 if (msg->FindString("decor", &newDecor) == B_OK) 185 _SetDecor(newDecor); 186 break; 187 } 188 189 case kMsgDecorInfo: 190 { 191 DecorInfo* decor = fDecorUtility.FindDecorator(fCurrentDecor); 192 if (decor == NULL) 193 break; 194 195 BString authorsText(decor->Authors().String()); 196 authorsText.ReplaceAll(", ", "\n\t"); 197 198 BString infoText(B_TRANSLATE("%decorName\n\n" 199 "Authors:\n\t%decorAuthors\n\n" 200 "URL: %decorURL\n" 201 "License: %decorLic\n\n" 202 "%decorDesc\n")); 203 204 205 infoText.ReplaceFirst("%decorName", decor->Name().String()); 206 infoText.ReplaceFirst("%decorAuthors", authorsText.String()); 207 infoText.ReplaceFirst("%decorLic", decor->LicenseName().String()); 208 infoText.ReplaceFirst("%decorURL", decor->SupportURL().String()); 209 infoText.ReplaceFirst("%decorDesc", decor->ShortDescription().String()); 210 211 BAlert *infoAlert = new BAlert(B_TRANSLATE("About decorator"), 212 infoText.String(), B_TRANSLATE("OK")); 213 infoAlert->SetFlags(infoAlert->Flags() | B_CLOSE_ON_ESCAPE); 214 infoAlert->Go(); 215 216 break; 217 } 218 219 case kMsgSetControlLook: 220 { 221 BString newControlLook; 222 if (msg->FindString("control_look", &newControlLook) == B_OK) { 223 BPrivate::set_control_look(newControlLook); 224 } 225 break; 226 } 227 228 case kMsgControlLookInfo: 229 { 230 BString infoText(B_TRANSLATE("Default Haiku ControlLook")); 231 BString path; 232 if (!BPrivate::get_control_look(path)) 233 break; 234 235 if (path.Length()) { 236 BFile file(path.String(), B_READ_ONLY); 237 if (file.InitCheck() != B_OK) 238 break; 239 240 BAppFileInfo info(&file); 241 struct version_info version; 242 if (info.InitCheck() != B_OK 243 || info.GetVersionInfo(&version, B_APP_VERSION_KIND) != B_OK) 244 break; 245 246 infoText = version.short_info; 247 infoText << "\n" << version.long_info; 248 } 249 250 BAlert *infoAlert = new BAlert(B_TRANSLATE("About control look"), 251 infoText.String(), B_TRANSLATE("OK")); 252 infoAlert->SetFlags(infoAlert->Flags() | B_CLOSE_ON_ESCAPE); 253 infoAlert->Go(); 254 255 break; 256 } 257 258 case kMsgArrowStyleSingle: 259 _SetDoubleScrollBarArrows(false); 260 break; 261 262 case kMsgArrowStyleDouble: 263 _SetDoubleScrollBarArrows(true); 264 break; 265 266 default: 267 BView::MessageReceived(msg); 268 break; 269 } 270 } 271 272 273 void 274 LookAndFeelSettingsView::_BuildDecorMenu() 275 { 276 fDecorMenu = new BPopUpMenu(B_TRANSLATE("Choose Decorator")); 277 278 // collect the current system decor settings 279 int32 count = fDecorUtility.CountDecorators(); 280 for (int32 i = 0; i < count; ++i) { 281 DecorInfo* decorator = fDecorUtility.DecoratorAt(i); 282 if (decorator == NULL) { 283 fprintf(stderr, "Decorator : error NULL entry @ %" B_PRId32 284 " / %" B_PRId32 "\n", i, count); 285 continue; 286 } 287 288 BString decorName = decorator->Name(); 289 290 BMessage* message = new BMessage(kMsgSetDecor); 291 message->AddString("decor", decorName); 292 293 BMenuItem* item = new BMenuItem(decorName, message); 294 295 fDecorMenu->AddItem(item); 296 } 297 298 _AdoptToCurrentDecor(); 299 } 300 301 302 void 303 LookAndFeelSettingsView::_BuildControlLookMenu() 304 { 305 BPathFinder pathFinder; 306 BStringList paths; 307 BDirectory dir; 308 BString currentLook; 309 310 BPrivate::get_control_look(currentLook); 311 312 fControlLookMenu = new BPopUpMenu(B_TRANSLATE("Choose ControlLook")); 313 314 BMessage* message = new BMessage(kMsgSetControlLook); 315 message->AddString("control_look", ""); 316 317 BMenuItem* item = new BMenuItem(B_TRANSLATE("Default"), message); 318 if (currentLook == "") 319 item->SetMarked(true); 320 fControlLookMenu->AddItem(item); 321 322 status_t error = pathFinder.FindPaths(B_FIND_PATH_ADD_ONS_DIRECTORY, 323 "control_look", paths); 324 325 for (int i = 0; i < paths.CountStrings(); ++i) { 326 if (error != B_OK || dir.SetTo(paths.StringAt(i)) != B_OK) 327 continue; 328 329 BEntry entry; 330 for (; dir.GetNextEntry(&entry) == B_OK;) { 331 BPath path(paths.StringAt(i), entry.Name()); 332 BString name(entry.Name()); 333 name.RemoveLast("ControlLook"); 334 name.Trim(); 335 336 message = new BMessage(kMsgSetControlLook); 337 message->AddString("control_look", path.Path()); 338 339 item = new BMenuItem(name.String(), message); 340 if (currentLook == path.Path()) 341 item->SetMarked(true); 342 fControlLookMenu->AddItem(item); 343 } 344 } 345 } 346 347 348 void 349 LookAndFeelSettingsView::_SetDecor(const BString& name) 350 { 351 _SetDecor(fDecorUtility.FindDecorator(name)); 352 } 353 354 355 void 356 LookAndFeelSettingsView::_SetDecor(DecorInfo* decorInfo) 357 { 358 if (fDecorUtility.SetDecorator(decorInfo) == B_OK) { 359 _AdoptToCurrentDecor(); 360 Window()->PostMessage(kMsgUpdate); 361 } 362 } 363 364 365 void 366 LookAndFeelSettingsView::_AdoptToCurrentDecor() 367 { 368 fCurrentDecor = fDecorUtility.CurrentDecorator()->Name(); 369 if (fSavedDecor.Length() == 0) 370 fSavedDecor = fCurrentDecor; 371 _AdoptInterfaceToCurrentDecor(); 372 } 373 374 void 375 LookAndFeelSettingsView::_AdoptInterfaceToCurrentDecor() 376 { 377 BMenuItem* item = fDecorMenu->FindItem(fCurrentDecor); 378 if (item != NULL) 379 item->SetMarked(true); 380 } 381 382 383 bool 384 LookAndFeelSettingsView::_DoubleScrollBarArrows() 385 { 386 scroll_bar_info info; 387 get_scroll_bar_info(&info); 388 389 return info.double_arrows; 390 } 391 392 393 void 394 LookAndFeelSettingsView::_SetDoubleScrollBarArrows(bool doubleArrows) 395 { 396 scroll_bar_info info; 397 get_scroll_bar_info(&info); 398 399 info.double_arrows = doubleArrows; 400 set_scroll_bar_info(&info); 401 402 if (doubleArrows) 403 fArrowStyleDouble->SetValue(B_CONTROL_ON); 404 else 405 fArrowStyleSingle->SetValue(B_CONTROL_ON); 406 407 Window()->PostMessage(kMsgUpdate); 408 } 409 410 411 bool 412 LookAndFeelSettingsView::IsDefaultable() 413 { 414 return fCurrentDecor != fDecorUtility.DefaultDecorator()->Name() 415 || _DoubleScrollBarArrows() != false; 416 } 417 418 419 void 420 LookAndFeelSettingsView::SetDefaults() 421 { 422 _SetDecor(fDecorUtility.DefaultDecorator()); 423 BPrivate::set_control_look(BString("")); 424 _SetDoubleScrollBarArrows(false); 425 } 426 427 428 bool 429 LookAndFeelSettingsView::IsRevertable() 430 { 431 return fCurrentDecor != fSavedDecor 432 || _DoubleScrollBarArrows() != fSavedDoubleArrowsValue; 433 } 434 435 436 void 437 LookAndFeelSettingsView::Revert() 438 { 439 if (IsRevertable()) { 440 _SetDecor(fSavedDecor); 441 _SetDoubleScrollBarArrows(fSavedDoubleArrowsValue); 442 } 443 } 444