* Copyright 2010-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
* Alexander von Gluck <kallisti5@unixzen.com>
* John Scipione <jscipione@gmail.com>
* Ryan Leavengood <leavengood@gmail.com>
*/
#include "LookAndFeelSettingsView.h"
#include <stdio.h>
#include <stdlib.h>
#include <Alert.h>
#include <Alignment.h>
#include <AppFileInfo.h>
#include <Box.h>
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <File.h>
#include <InterfaceDefs.h>
#include <InterfacePrivate.h>
#include <LayoutBuilder.h>
#include <Locale.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Path.h>
#include <PathFinder.h>
#include <PopUpMenu.h>
#include <ScrollBar.h>
#include <StringView.h>
#include <Size.h>
#include <Slider.h>
#include <SpaceLayoutItem.h>
#include <StringView.h>
#include <TextView.h>
#include "AppearanceWindow.h"
#include "FakeScrollBar.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "DecorSettingsView"
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;
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;
_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;
_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));
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));
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);
}
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;
}
}
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"));
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);
}
}