384 lines
9.7 KiB
C++
384 lines
9.7 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
GUIPrefs.cpp
|
|
|
|
Brian Gunlogson
|
|
Joshua Haberman
|
|
Dominic Mazzoni
|
|
James Crook
|
|
|
|
|
|
*******************************************************************//**
|
|
|
|
\class GUIPrefs
|
|
\brief A PrefsPanel for general GUI preferences.
|
|
|
|
*//*******************************************************************/
|
|
|
|
#include "../Audacity.h"
|
|
#include "GUIPrefs.h"
|
|
|
|
#include "../Experimental.h"
|
|
|
|
#include <wx/app.h>
|
|
#include <wx/defs.h>
|
|
|
|
#include "../FileNames.h"
|
|
#include "../Languages.h"
|
|
#include "../Theme.h"
|
|
#include "../Prefs.h"
|
|
#include "../ShuttleGui.h"
|
|
|
|
#include "GUISettings.h"
|
|
|
|
#include "ThemePrefs.h"
|
|
#include "../AColor.h"
|
|
#include "../widgets/AudacityMessageBox.h"
|
|
|
|
GUIPrefs::GUIPrefs(wxWindow * parent, wxWindowID winid)
|
|
/* i18n-hint: refers to Audacity's user interface settings */
|
|
: PrefsPanel(parent, winid, XO("Interface"))
|
|
{
|
|
Populate();
|
|
}
|
|
|
|
GUIPrefs::~GUIPrefs()
|
|
{
|
|
}
|
|
|
|
ComponentInterfaceSymbol GUIPrefs::GetSymbol()
|
|
{
|
|
return GUI_PREFS_PLUGIN_SYMBOL;
|
|
}
|
|
|
|
TranslatableString GUIPrefs::GetDescription()
|
|
{
|
|
return XO("Preferences for GUI");
|
|
}
|
|
|
|
wxString GUIPrefs::HelpPageName()
|
|
{
|
|
return "Interface_Preferences";
|
|
}
|
|
|
|
void GUIPrefs::GetRangeChoices(
|
|
TranslatableStrings *pChoices,
|
|
wxArrayStringEx *pCodes,
|
|
int *pDefaultRangeIndex
|
|
)
|
|
{
|
|
static const auto sCodes = {
|
|
wxT("36") ,
|
|
wxT("48") ,
|
|
wxT("60") ,
|
|
wxT("72") ,
|
|
wxT("84") ,
|
|
wxT("96") ,
|
|
wxT("120") ,
|
|
wxT("145") ,
|
|
};
|
|
if (pCodes)
|
|
*pCodes = sCodes;
|
|
|
|
static const std::initializer_list<TranslatableString> sChoices = {
|
|
XO("-36 dB (shallow range for high-amplitude editing)") ,
|
|
XO("-48 dB (PCM range of 8 bit samples)") ,
|
|
XO("-60 dB (PCM range of 10 bit samples)") ,
|
|
XO("-72 dB (PCM range of 12 bit samples)") ,
|
|
XO("-84 dB (PCM range of 14 bit samples)") ,
|
|
XO("-96 dB (PCM range of 16 bit samples)") ,
|
|
XO("-120 dB (approximate limit of human hearing)") ,
|
|
XO("-145 dB (PCM range of 24 bit samples)") ,
|
|
};
|
|
|
|
if (pChoices)
|
|
*pChoices = sChoices;
|
|
|
|
if (pDefaultRangeIndex)
|
|
*pDefaultRangeIndex = 2; // 60 == ENV_DB_RANGE
|
|
}
|
|
|
|
void GUIPrefs::Populate()
|
|
{
|
|
// First any pre-processing for constructing the GUI.
|
|
GetLanguages(mLangCodes, mLangNames);
|
|
|
|
GetRangeChoices(&mRangeChoices, &mRangeCodes, &mDefaultRangeIndex);
|
|
|
|
#if 0
|
|
mLangCodes.insert( mLangCodes.end(), {
|
|
// only for testing...
|
|
"kg" ,
|
|
"ep" ,
|
|
} );
|
|
|
|
mLangNames.insert( mLangNames.end(), {
|
|
"Klingon" ,
|
|
"Esperanto" ,
|
|
} );
|
|
#endif
|
|
|
|
//------------------------- Main section --------------------
|
|
// Now construct the GUI itself.
|
|
// Use 'eIsCreatingFromPrefs' so that the GUI is
|
|
// initialised with values from gPrefs.
|
|
ShuttleGui S(this, eIsCreatingFromPrefs);
|
|
PopulateOrExchange(S);
|
|
// ----------------------- End of main section --------------
|
|
}
|
|
|
|
ChoiceSetting GUIManualLocation{
|
|
wxT("/GUI/Help"),
|
|
{
|
|
ByColumns,
|
|
{ XO("Local") , XO("From Internet") , },
|
|
{ wxT("Local") , wxT("FromInternet") , }
|
|
},
|
|
0 // "Local"
|
|
};
|
|
|
|
constexpr int defaultTheme =
|
|
#ifdef EXPERIMENTAL_DA
|
|
2 // "dark"
|
|
#else
|
|
1 // "light"
|
|
#endif
|
|
;
|
|
|
|
ChoiceSetting GUITheme{
|
|
wxT("/GUI/Theme"),
|
|
{
|
|
ByColumns,
|
|
{
|
|
/* i18n-hint: describing the "classic" or traditional
|
|
appearance of older versions of Audacity */
|
|
XO("Classic") ,
|
|
/* i18n-hint: Light meaning opposite of dark */
|
|
XO("Light") ,
|
|
XO("Dark") ,
|
|
/* i18n-hint: greater difference between foreground and
|
|
background colors */
|
|
XO("High Contrast") ,
|
|
/* i18n-hint: user defined */
|
|
XO("Custom") ,
|
|
},
|
|
{
|
|
wxT("classic") ,
|
|
wxT("light") ,
|
|
wxT("dark") ,
|
|
wxT("high-contrast") ,
|
|
wxT("custom") ,
|
|
}
|
|
},
|
|
defaultTheme
|
|
};
|
|
|
|
void GUIPrefs::PopulateOrExchange(ShuttleGui & S)
|
|
{
|
|
S.SetBorder(2);
|
|
S.StartScroller();
|
|
|
|
S.StartStatic(XO("Display"));
|
|
{
|
|
S.StartMultiColumn(2);
|
|
{
|
|
|
|
S.TieChoice( XO("&Language:"),
|
|
{
|
|
wxT("/Locale/Language"),
|
|
{ ByColumns, mLangNames, mLangCodes }
|
|
}
|
|
);
|
|
|
|
S.TieChoice( XO("Location of &Manual:"), GUIManualLocation);
|
|
|
|
S.TieChoice( XO("Th&eme:"), GUITheme);
|
|
|
|
S.TieChoice( XO("Meter dB &range:"),
|
|
{
|
|
ENV_DB_KEY,
|
|
{ ByColumns, mRangeChoices, mRangeCodes },
|
|
mDefaultRangeIndex
|
|
}
|
|
);
|
|
}
|
|
S.EndMultiColumn();
|
|
// S.AddSpace(10);
|
|
// JKC: This is a silly preference. Kept here as a reminder that we may
|
|
// later want to have configurable button order.
|
|
// S.TieCheckBox(XO("&Ergonomic order of Transport Toolbar buttons"),
|
|
// wxT("/GUI/ErgonomicTransportButtons"),
|
|
// true);
|
|
|
|
}
|
|
S.EndStatic();
|
|
|
|
S.StartStatic(XO("Options"));
|
|
{
|
|
// Start wording of options with a verb, if possible.
|
|
S.TieCheckBox(XO("Show 'How to Get &Help' at launch"),
|
|
{wxT("/GUI/ShowSplashScreen"),
|
|
true});
|
|
S.TieCheckBox(XO("Show e&xtra menus"),
|
|
{wxT("/GUI/ShowExtraMenus"),
|
|
false});
|
|
#ifdef EXPERIMENTAL_THEME_PREFS
|
|
// We do not want to make this option mainstream. It's a
|
|
// convenience for developers.
|
|
S.TieCheckBox(XO("Show alternative &styling (Mac vs PC)"),
|
|
{wxT("/GUI/ShowMac"),
|
|
false});
|
|
#endif
|
|
S.TieCheckBox(XO("&Beep on completion of longer activities"),
|
|
{wxT("/GUI/BeepOnCompletion"),
|
|
false});
|
|
S.TieCheckBox(XO("Re&tain labels if selection snaps to a label"),
|
|
{wxT("/GUI/RetainLabels"),
|
|
false});
|
|
S.TieCheckBox(XO("B&lend system and Audacity theme"),
|
|
{wxT("/GUI/BlendThemes"),
|
|
true});
|
|
#ifndef __WXMAC__
|
|
/* i18n-hint: RTL stands for 'Right to Left' */
|
|
S.TieCheckBox(XO("Use mostly Left-to-Right layouts in RTL languages"),
|
|
{"/GUI/RtlWorkaround",
|
|
true});
|
|
#endif
|
|
}
|
|
S.EndStatic();
|
|
|
|
S.EndScroller();
|
|
}
|
|
|
|
bool GUIPrefs::Commit()
|
|
{
|
|
ShuttleGui S(this, eIsSavingToPrefs);
|
|
PopulateOrExchange(S);
|
|
|
|
// If language has changed, we want to change it now, not on the next reboot.
|
|
wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT(""));
|
|
wxString usedLang = SetLang(lang);
|
|
// Bug 1523: Previously didn't check no-language (=System Language)
|
|
if (!(lang.empty()) && (lang != usedLang)) {
|
|
// lang was not usable and is not system language. We got overridden.
|
|
gPrefs->Write(wxT("/Locale/Language"), usedLang);
|
|
gPrefs->Flush();
|
|
}
|
|
|
|
// Reads preference GUITheme
|
|
theTheme.LoadPreferredTheme();
|
|
ThemePrefs::ApplyUpdatedImages();
|
|
|
|
return true;
|
|
}
|
|
|
|
wxString GUIPrefs::InitLang( wxString langCode )
|
|
{
|
|
if ( langCode.empty() )
|
|
langCode = gPrefs->Read(wxT("/Locale/Language"), wxEmptyString);
|
|
|
|
// Use the system default language if one wasn't specified or if the user selected System.
|
|
if (langCode.empty())
|
|
{
|
|
langCode = GetSystemLanguageCode();
|
|
}
|
|
|
|
// Initialize the language
|
|
return SetLang(langCode);
|
|
}
|
|
|
|
#define IPC_APPL wxT("audacity")
|
|
static std::unique_ptr<wxLocale> sLocale;
|
|
|
|
wxString GUIPrefs::SetLang( const wxString & lang )
|
|
{
|
|
wxString result = lang;
|
|
|
|
sLocale.reset();
|
|
|
|
#if defined(__WXMAC__)
|
|
// This should be reviewed again during the wx3 conversion.
|
|
|
|
// On OSX, if the LANG environment variable isn't set when
|
|
// using a language like Japanese, an assertion will trigger
|
|
// because conversion to Japanese from "?" doesn't return a
|
|
// valid length, so make OSX happy by defining/overriding
|
|
// the LANG environment variable with U.S. English for now.
|
|
wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8"));
|
|
#endif
|
|
|
|
const wxLanguageInfo *info = NULL;
|
|
if (!lang.empty() && lang != wxT("System")) {
|
|
info = wxLocale::FindLanguageInfo(lang);
|
|
if (!info)
|
|
::AudacityMessageBox(
|
|
XO("Language \"%s\" is unknown").Format( lang ) );
|
|
}
|
|
if (!info)
|
|
{
|
|
result = GetSystemLanguageCode();
|
|
info = wxLocale::FindLanguageInfo(result);
|
|
if (!info)
|
|
return result;
|
|
}
|
|
sLocale = std::make_unique<wxLocale>(info->Language);
|
|
|
|
for( const auto &path : FileNames::AudacityPathList() )
|
|
sLocale->AddCatalogLookupPathPrefix( path );
|
|
|
|
// LL: Must add the wxWidgets catalog manually since the search
|
|
// paths were not set up when mLocale was created. The
|
|
// catalogs are search in LIFO order, so add wxstd first.
|
|
sLocale->AddCatalog(wxT("wxstd"));
|
|
|
|
// AUDACITY_NAME is legitimately used on some *nix configurations.
|
|
#ifdef AUDACITY_NAME
|
|
sLocale->AddCatalog(wxT(AUDACITY_NAME));
|
|
#else
|
|
sLocale->AddCatalog(IPC_APPL);
|
|
#endif
|
|
|
|
// Initialize internationalisation (number formats etc.)
|
|
//
|
|
// This must go _after_ creating the wxLocale instance because
|
|
// creating the wxLocale instance sets the application-wide locale.
|
|
|
|
Internat::Init();
|
|
|
|
// Unused strings that we want to be translated, even though
|
|
// we're not using them yet...
|
|
using future1 = decltype( XO("Master Gain Control") );
|
|
|
|
#ifdef __WXMAC__
|
|
wxApp::s_macHelpMenuTitleName = _("&Help");
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
wxString GUIPrefs::GetLang()
|
|
{
|
|
if (sLocale)
|
|
return sLocale->GetSysName();
|
|
else
|
|
return {};
|
|
}
|
|
|
|
int ShowClippingPrefsID()
|
|
{
|
|
static int value = wxNewId();
|
|
return value;
|
|
}
|
|
|
|
namespace{
|
|
PrefsPanel::Registration sAttachment{ "GUI",
|
|
[](wxWindow *parent, wxWindowID winid, AudacityProject *)
|
|
{
|
|
wxASSERT(parent); // to justify safenew
|
|
return safenew GUIPrefs(parent, winid);
|
|
}
|
|
};
|
|
}
|