/* * Copyright 2010-2020 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT license. * * Authors: * Stephan Aßmus * Alexander von Gluck * John Scipione * Ryan Leavengood */ #include "LookAndFeelSettingsView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "APRWindow.h" #include "FakeScrollBar.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "DecorSettingsView" // This was not renamed to keep from breaking translations static const int32 kMsgSetDecor = 'deco'; static const int32 kMsgDecorInfo = 'idec'; static const int32 kMsgSetControlLook = 'ctlk'; static const int32 kMsgControlLookInfo = 'iclk'; static const int32 kMsgDoubleScrollBarArrows = 'dsba'; static const int32 kMsgArrowStyleSingle = 'mass'; static const int32 kMsgArrowStyleDouble = 'masd'; static const bool kDefaultDoubleScrollBarArrowsSetting = false; // #pragma mark - LookAndFeelSettingsView LookAndFeelSettingsView::LookAndFeelSettingsView(const char* name) : BView(name, 0), fDecorInfoButton(NULL), fDecorMenuField(NULL), fDecorMenu(NULL), fControlLookInfoButton(NULL), fControlLookMenuField(NULL), fControlLookMenu(NULL), fArrowStyleSingle(NULL), fArrowStyleDouble(NULL), fSavedDecor(NULL), fCurrentDecor(NULL), fSavedControlLook(NULL), fCurrentControlLook(NULL), fSavedDoubleArrowsValue(_DoubleScrollBarArrows()) { fCurrentDecor = fDecorUtility.CurrentDecorator()->ShortcutName(); fSavedDecor = fCurrentDecor; // Decorator menu _BuildDecorMenu(); fDecorMenuField = new BMenuField("decorator", B_TRANSLATE("Decorator:"), fDecorMenu); fDecorInfoButton = new BButton(B_TRANSLATE("About"), new BMessage(kMsgDecorInfo)); BPrivate::get_control_look(fCurrentControlLook); fSavedControlLook = fCurrentControlLook; // ControlLook menu _BuildControlLookMenu(); fControlLookMenuField = new BMenuField("controllook", B_TRANSLATE("ControlLook:"), fControlLookMenu); fControlLookMenuField->SetToolTip( B_TRANSLATE("No effect on running applications")); fControlLookInfoButton = new BButton(B_TRANSLATE("About"), new BMessage(kMsgControlLookInfo)); // scroll bar arrow style BBox* arrowStyleBox = new BBox("arrow style"); arrowStyleBox->SetLabel(B_TRANSLATE("Arrow style")); fArrowStyleSingle = new FakeScrollBar(true, false, new BMessage(kMsgArrowStyleSingle)); fArrowStyleDouble = new FakeScrollBar(true, true, new BMessage(kMsgArrowStyleDouble)); BView* arrowStyleView; arrowStyleView = BLayoutBuilder::Group<>() .AddGroup(B_VERTICAL, 1) .Add(new BStringView("single", B_TRANSLATE("Single:"))) .Add(fArrowStyleSingle) .AddStrut(B_USE_DEFAULT_SPACING) .Add(new BStringView("double", B_TRANSLATE("Double:"))) .Add(fArrowStyleDouble) .SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) .End() .View(); arrowStyleBox->AddChild(arrowStyleView); arrowStyleBox->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER)); arrowStyleBox->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); BStringView* scrollBarLabel = new BStringView("scroll bar", B_TRANSLATE("Scroll bar:")); scrollBarLabel->SetExplicitAlignment( BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP)); // control layout BLayoutBuilder::Grid<>(this, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) .Add(fDecorMenuField->CreateLabelLayoutItem(), 0, 0) .Add(fDecorMenuField->CreateMenuBarLayoutItem(), 1, 0) .Add(fDecorInfoButton, 2, 0) .Add(fControlLookMenuField->CreateLabelLayoutItem(), 0, 1) .Add(fControlLookMenuField->CreateMenuBarLayoutItem(), 1, 1) .Add(fControlLookInfoButton, 2, 1) .Add(scrollBarLabel, 0, 2) .Add(arrowStyleBox, 1, 2) .AddGlue(0, 3) .SetInsets(B_USE_WINDOW_SPACING); // TODO : Decorator Preview Image? } LookAndFeelSettingsView::~LookAndFeelSettingsView() { } void LookAndFeelSettingsView::AttachedToWindow() { AdoptParentColors(); if (Parent() == NULL) SetViewUIColor(B_PANEL_BACKGROUND_COLOR); fDecorMenu->SetTargetForItems(this); fDecorInfoButton->SetTarget(this); fControlLookMenu->SetTargetForItems(this); fControlLookInfoButton->SetTarget(this); fArrowStyleSingle->SetTarget(this); fArrowStyleDouble->SetTarget(this); if (fSavedDoubleArrowsValue) fArrowStyleDouble->SetValue(B_CONTROL_ON); else fArrowStyleSingle->SetValue(B_CONTROL_ON); } void LookAndFeelSettingsView::MessageReceived(BMessage* message) { switch (message->what) { case kMsgSetDecor: { BString newDecor; if (message->FindString("decor", &newDecor) == B_OK) _SetDecor(newDecor); break; } case kMsgDecorInfo: { DecorInfo* decor = fDecorUtility.FindDecorator(fCurrentDecor); if (decor == NULL) break; BString authorsText(decor->Authors().String()); authorsText.ReplaceAll(", ", "\n\t"); BString infoText(B_TRANSLATE("%decorName\n\n" "Authors:\n\t%decorAuthors\n\n" "URL: %decorURL\n" "License: %decorLic\n\n" "%decorDesc\n")); infoText.ReplaceFirst("%decorName", decor->Name().String()); infoText.ReplaceFirst("%decorAuthors", authorsText.String()); infoText.ReplaceFirst("%decorLic", decor->LicenseName().String()); infoText.ReplaceFirst("%decorURL", decor->SupportURL().String()); infoText.ReplaceFirst("%decorDesc", decor->ShortDescription().String()); BAlert* infoAlert = new BAlert(B_TRANSLATE("About decorator"), infoText.String(), B_TRANSLATE("OK")); infoAlert->SetFlags(infoAlert->Flags() | B_CLOSE_ON_ESCAPE); infoAlert->Go(); break; } case kMsgSetControlLook: { BString controlLook; if (message->FindString("control_look", &controlLook) == B_OK) _SetControlLook(controlLook); break; } case kMsgControlLookInfo: { BString infoText(B_TRANSLATE("Default Haiku ControlLook")); BString path; if (!BPrivate::get_control_look(path)) break; if (path.Length() > 0) { BFile file(path.String(), B_READ_ONLY); if (file.InitCheck() != B_OK) break; BAppFileInfo info(&file); struct version_info version; if (info.InitCheck() != B_OK || info.GetVersionInfo(&version, B_APP_VERSION_KIND) != B_OK) break; infoText = version.short_info; infoText << "\n" << version.long_info; } BAlert* infoAlert = new BAlert(B_TRANSLATE("About control look"), infoText.String(), B_TRANSLATE("OK")); infoAlert->SetFlags(infoAlert->Flags() | B_CLOSE_ON_ESCAPE); infoAlert->Go(); break; } case kMsgArrowStyleSingle: _SetDoubleScrollBarArrows(false); break; case kMsgArrowStyleDouble: _SetDoubleScrollBarArrows(true); break; default: BView::MessageReceived(message); break; } } // #pragma mark - LookAndFeelSettingsView private methods void LookAndFeelSettingsView::_SetDecor(const BString& name) { _SetDecor(fDecorUtility.FindDecorator(name)); } void LookAndFeelSettingsView::_SetDecor(DecorInfo* decorInfo) { if (fDecorUtility.SetDecorator(decorInfo) == B_OK) { fCurrentDecor = fDecorUtility.CurrentDecorator()->ShortcutName(); BString decorName = fDecorUtility.CurrentDecorator()->Name(); fDecorMenu->FindItem(_DecorLabel(decorName))->SetMarked(true); Window()->PostMessage(kMsgUpdate); } } void LookAndFeelSettingsView::_BuildDecorMenu() { fDecorMenu = new BPopUpMenu(B_TRANSLATE("Choose Decorator")); // collect the current system decor settings int32 count = fDecorUtility.CountDecorators(); for (int32 i = 0; i < count; ++i) { DecorInfo* decor = fDecorUtility.DecoratorAt(i); if (decor == NULL) { fprintf(stderr, "Decorator : error NULL entry @ %" B_PRId32 " / %" B_PRId32 "\n", i, count); continue; } BMessage* message = new BMessage(kMsgSetDecor); message->AddString("decor", decor->ShortcutName()); BMenuItem* item = new BMenuItem(_DecorLabel(decor->Name()), message); fDecorMenu->AddItem(item); if (decor->ShortcutName() == fCurrentDecor) item->SetMarked(true); } } const char* LookAndFeelSettingsView::_DecorLabel(const BString& name) { BString label(name); return label.RemoveLast("Decorator").Trim().String(); } void LookAndFeelSettingsView::_SetControlLook(const BString& path) { fCurrentControlLook = path; BPrivate::set_control_look(path); if (path.Length() > 0) { BEntry entry(path.String()); const char* label = _ControlLookLabel(entry.Name()); fControlLookMenu->FindItem(label)->SetMarked(true); } else fControlLookMenu->FindItem(B_TRANSLATE("Default"))->SetMarked(true); Window()->PostMessage(kMsgUpdate); } void LookAndFeelSettingsView::_BuildControlLookMenu() { BPathFinder pathFinder; BStringList paths; BDirectory dir; fControlLookMenu = new BPopUpMenu(B_TRANSLATE("Choose ControlLook")); BMessage* message = new BMessage(kMsgSetControlLook); message->AddString("control_look", ""); BMenuItem* item = new BMenuItem(B_TRANSLATE("Default"), message); if (fCurrentControlLook.Length() == 0) item->SetMarked(true); fControlLookMenu->AddItem(item); status_t error = pathFinder.FindPaths(B_FIND_PATH_ADD_ONS_DIRECTORY, "control_look", paths); int32 count = paths.CountStrings(); for (int32 i = 0; i < count; ++i) { if (error != B_OK || dir.SetTo(paths.StringAt(i)) != B_OK) continue; BEntry entry; while (dir.GetNextEntry(&entry) == B_OK) { BPath path(paths.StringAt(i), entry.Name()); message = new BMessage(kMsgSetControlLook); message->AddString("control_look", path.Path()); item = new BMenuItem(_ControlLookLabel(entry.Name()), message); fControlLookMenu->AddItem(item); if (BString(path.Path()) == fCurrentControlLook) item->SetMarked(true); } } } const char* LookAndFeelSettingsView::_ControlLookLabel(const char* name) { BString label(name); return label.RemoveLast("ControlLook").Trim().String(); } bool LookAndFeelSettingsView::_DoubleScrollBarArrows() { scroll_bar_info info; get_scroll_bar_info(&info); return info.double_arrows; } void LookAndFeelSettingsView::_SetDoubleScrollBarArrows(bool doubleArrows) { scroll_bar_info info; get_scroll_bar_info(&info); if (info.double_arrows == doubleArrows) return; info.double_arrows = doubleArrows; set_scroll_bar_info(&info); if (doubleArrows) fArrowStyleDouble->SetValue(B_CONTROL_ON); else fArrowStyleSingle->SetValue(B_CONTROL_ON); Window()->PostMessage(kMsgUpdate); } bool LookAndFeelSettingsView::IsDefaultable() { return fCurrentDecor != fDecorUtility.DefaultDecorator()->ShortcutName() || fCurrentControlLook.Length() != 0 || _DoubleScrollBarArrows() != false; } void LookAndFeelSettingsView::SetDefaults() { _SetDecor(fDecorUtility.DefaultDecorator()); _SetControlLook(BString("")); _SetDoubleScrollBarArrows(false); } bool LookAndFeelSettingsView::IsRevertable() { return fCurrentDecor != fSavedDecor || fCurrentControlLook != fSavedControlLook || _DoubleScrollBarArrows() != fSavedDoubleArrowsValue; } void LookAndFeelSettingsView::Revert() { if (IsRevertable()) { _SetDecor(fSavedDecor); _SetControlLook(fSavedControlLook); _SetDoubleScrollBarArrows(fSavedDoubleArrowsValue); } }