1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   GUIPrefs.cpp
6 
7   Brian Gunlogson
8   Joshua Haberman
9   Dominic Mazzoni
10   James Crook
11 
12 
13 *******************************************************************//**
14 
15 \class GUIPrefs
16 \brief A PrefsPanel for general GUI preferences.
17 
18 *//*******************************************************************/
19 
20 
21 #include "GUIPrefs.h"
22 
23 #include <wx/app.h>
24 #include <wx/defs.h>
25 
26 #include "FileNames.h"
27 #include "Languages.h"
28 #include "Theme.h"
29 #include "Prefs.h"
30 #include "../ShuttleGui.h"
31 
32 #include "Decibels.h"
33 
34 #include "ThemePrefs.h"
35 #include "AColor.h"
36 #include "../widgets/AudacityMessageBox.h"
37 
GUIPrefs(wxWindow * parent,wxWindowID winid)38 GUIPrefs::GUIPrefs(wxWindow * parent, wxWindowID winid)
39 /* i18n-hint: refers to Audacity's user interface settings */
40 :  PrefsPanel(parent, winid, XC("Interface", "GUI"))
41 {
42    Populate();
43 }
44 
~GUIPrefs()45 GUIPrefs::~GUIPrefs()
46 {
47 }
48 
GetSymbol()49 ComponentInterfaceSymbol GUIPrefs::GetSymbol()
50 {
51    return GUI_PREFS_PLUGIN_SYMBOL;
52 }
53 
GetDescription()54 TranslatableString GUIPrefs::GetDescription()
55 {
56    return XO("Preferences for GUI");
57 }
58 
HelpPageName()59 ManualPageID GUIPrefs::HelpPageName()
60 {
61    return "Interface_Preferences";
62 }
63 
GetRangeChoices(TranslatableStrings * pChoices,wxArrayStringEx * pCodes,int * pDefaultRangeIndex)64 void GUIPrefs::GetRangeChoices(
65    TranslatableStrings *pChoices,
66    wxArrayStringEx *pCodes,
67    int *pDefaultRangeIndex
68 )
69 {
70    static const auto sCodes = {
71       wxT("36") ,
72       wxT("48") ,
73       wxT("60") ,
74       wxT("72") ,
75       wxT("84") ,
76       wxT("96") ,
77       wxT("120") ,
78       wxT("145") ,
79    };
80    if (pCodes)
81       *pCodes = sCodes;
82 
83    static const std::initializer_list<TranslatableString> sChoices = {
84       XO("-36 dB (shallow range for high-amplitude editing)") ,
85       XO("-48 dB (PCM range of 8 bit samples)") ,
86       XO("-60 dB (PCM range of 10 bit samples)") ,
87       XO("-72 dB (PCM range of 12 bit samples)") ,
88       XO("-84 dB (PCM range of 14 bit samples)") ,
89       XO("-96 dB (PCM range of 16 bit samples)") ,
90       XO("-120 dB (approximate limit of human hearing)") ,
91       XO("-145 dB (PCM range of 24 bit samples)") ,
92    };
93 
94    if (pChoices)
95       *pChoices = sChoices;
96 
97    if (pDefaultRangeIndex)
98       *pDefaultRangeIndex = 2; // 60 == ENV_DB_RANGE
99 }
100 
Populate()101 void GUIPrefs::Populate()
102 {
103    // First any pre-processing for constructing the GUI.
104    Languages::GetLanguages(
105       FileNames::AudacityPathList(), mLangCodes, mLangNames);
106 
107    GetRangeChoices(&mRangeChoices, &mRangeCodes, &mDefaultRangeIndex);
108 
109 #if 0
110    mLangCodes.insert( mLangCodes.end(), {
111       // only for testing...
112       "kg" ,
113       "ep" ,
114    } );
115 
116    mLangNames.insert( mLangNames.end(), {
117       "Klingon" ,
118       "Esperanto" ,
119    } );
120 #endif
121 
122    //------------------------- Main section --------------------
123    // Now construct the GUI itself.
124    // Use 'eIsCreatingFromPrefs' so that the GUI is
125    // initialised with values from gPrefs.
126    ShuttleGui S(this, eIsCreatingFromPrefs);
127    PopulateOrExchange(S);
128    // ----------------------- End of main section --------------
129 }
130 
131 ChoiceSetting GUIManualLocation{
132    wxT("/GUI/Help"),
133    {
134       ByColumns,
135       { XO("Local") ,  XO("From Internet") , },
136       { wxT("Local") , wxT("FromInternet") , }
137    },
138    0 // "Local"
139 };
140 
PopulateOrExchange(ShuttleGui & S)141 void GUIPrefs::PopulateOrExchange(ShuttleGui & S)
142 {
143    S.SetBorder(2);
144    S.StartScroller();
145 
146    S.StartStatic(XO("Display"));
147    {
148       S.StartMultiColumn(2);
149       {
150 
151          S.TieChoice( XXO("&Language:"),
152             {
153                wxT("/Locale/Language"),
154                { ByColumns, mLangNames, mLangCodes }
155             }
156          );
157 
158          S.TieChoice( XXO("Location of &Manual:"), GUIManualLocation);
159 
160          S.TieChoice( XXO("Th&eme:"), GUITheme());
161 
162          S.TieChoice( XXO("Meter dB &range:"),
163             {
164                DecibelScaleCutoff.GetPath(),
165                { ByColumns, mRangeChoices, mRangeCodes },
166                mDefaultRangeIndex
167             }
168          );
169       }
170       S.EndMultiColumn();
171 
172    }
173    S.EndStatic();
174 
175    S.StartStatic(XO("Options"));
176    {
177       // Start wording of options with a verb, if possible.
178       S.TieCheckBox(XXO("Show 'How to Get &Help' at launch"),
179                     {wxT("/GUI/ShowSplashScreen"),
180                      true});
181       S.TieCheckBox(XXO("Show e&xtra menus"),
182                     {wxT("/GUI/ShowExtraMenus"),
183                      false});
184 #ifdef EXPERIMENTAL_THEME_PREFS
185       // We do not want to make this option mainstream.  It's a
186       // convenience for developers.
187       S.TieCheckBox(XXO("Show alternative &styling (Mac vs PC)"),
188                     {wxT("/GUI/ShowMac"),
189                      false});
190 #endif
191       S.TieCheckBox(XXO("&Beep on completion of longer activities"),
192                     {wxT("/GUI/BeepOnCompletion"),
193                      false});
194       S.TieCheckBox(XXO("Re&tain labels if selection snaps to a label"),
195                     {wxT("/GUI/RetainLabels"),
196                      false});
197       S.TieCheckBox(XXO("B&lend system and Audacity theme"),
198                      GUIBlendThemes);
199 #ifndef __WXMAC__
200       /* i18n-hint: RTL stands for 'Right to Left'  */
201       S.TieCheckBox(XXO("Use mostly Left-to-Right layouts in RTL languages"),
202          {"/GUI/RtlWorkaround",
203           true});
204 #endif
205 #ifdef EXPERIMENTAL_CEE_NUMBERS_OPTION
206       S.TieCheckBox(XXO("Never use comma as decimal point"),
207                     {wxT("/Locale/CeeNumberFormat"),
208                      false});
209 #endif
210    }
211    S.EndStatic();
212 
213    S.StartStatic(XO("Timeline"));
214    {
215       S.TieCheckBox(XXO("Show Timeline Tooltips"),
216                     {wxT("/QuickPlay/ToolTips"),
217                      true});
218       S.TieCheckBox(XXO("Show Scrub Ruler"),
219                     {wxT("/QuickPlay/ScrubbingEnabled"),
220                      false});
221    }
222    S.EndStatic();
223 
224    S.EndScroller();
225 }
226 
Commit()227 bool GUIPrefs::Commit()
228 {
229    ShuttleGui S(this, eIsSavingToPrefs);
230    PopulateOrExchange(S);
231 
232    // If language has changed, we want to change it now, not on the next reboot.
233    wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT(""));
234    wxString usedLang = SetLang(lang);
235    // Bug 1523: Previously didn't check no-language (=System Language)
236    if (!(lang.empty() || lang == L"System") && (lang != usedLang)) {
237       // lang was not usable and is not system language.  We got overridden.
238       gPrefs->Write(wxT("/Locale/Language"), usedLang);
239       gPrefs->Flush();
240    }
241 
242    // Reads preference GUITheme
243    {
244       wxBusyCursor busy;
245       theTheme.LoadPreferredTheme();
246    }
247    ThemePrefs::ApplyUpdatedImages();
248 
249    return true;
250 }
251 
SetLang(const wxString & lang)252 wxString GUIPrefs::SetLang( const wxString & lang )
253 {
254    auto result = Languages::SetLang(FileNames::AudacityPathList(), lang);
255    if (!(lang.empty() || lang == L"System") && result != lang)
256       ::AudacityMessageBox(
257          XO("Language \"%s\" is unknown").Format( lang ) );
258 
259 #ifdef EXPERIMENTAL_CEE_NUMBERS_OPTION
260    bool forceCeeNumbers;
261    gPrefs->Read(wxT("/Locale/CeeNumberFormat"), &forceCeeNumbers, false);
262    if( forceCeeNumbers )
263       Internat::SetCeeNumberFormat();
264 #endif
265 
266 #ifdef __WXMAC__
267       wxApp::s_macHelpMenuTitleName = _("&Help");
268 #endif
269 
270    return result;
271 }
272 
ShowClippingPrefsID()273 int ShowClippingPrefsID()
274 {
275    static int value = wxNewId();
276    return value;
277 }
278 
ShowTrackNameInWaveformPrefsID()279 int ShowTrackNameInWaveformPrefsID()
280 {
281    static int value = wxNewId();
282    return value;
283 }
284 
285 namespace{
286 PrefsPanel::Registration sAttachment{ "GUI",
287    [](wxWindow *parent, wxWindowID winid, AudacityProject *)
__anonf6f73c4e0202() 288    {
289       wxASSERT(parent); // to justify safenew
290       return safenew GUIPrefs(parent, winid);
291    }
292 };
293 }
294