1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   ThemePrefs.cpp
6 
7   James Crook
8 
9   Audacity is free software.
10   This file is licensed under the wxWidgets license, see License.txt
11 
12 ********************************************************************//**
13 
14 \class ThemePrefs
15 \brief A PrefsPanel that configures dynamic loading of Theme
16 icons and colours.
17 
18 Provides:
19  - Button to save current theme as a single png image.
20  - Button to load theme from a single png image.
21  - Button to save current theme to multiple png images.
22  - Button to load theme from multiple png images.
23  - (Optional) Button to save theme as Cee data.
24  - Button to read theme from default values in program.
25  - CheckBox for loading custom themes at startup.
26 
27 \see \ref Themability
28 
29 *//********************************************************************/
30 
31 
32 #include "ThemePrefs.h"
33 
34 #include <wx/app.h>
35 #include <wx/wxprec.h>
36 #include "Prefs.h"
37 #include "Theme.h"
38 #include "../ShuttleGui.h"
39 #include "AColor.h"
40 
41 wxDEFINE_EVENT(EVT_THEME_CHANGE, wxCommandEvent);
42 
43 enum eThemePrefsIds {
44    idLoadThemeCache=7000,
45    idSaveThemeCache,
46    idLoadThemeComponents,
47    idSaveThemeComponents,
48    idReadThemeInternal,
49    idSaveThemeAsCode
50 };
51 
BEGIN_EVENT_TABLE(ThemePrefs,PrefsPanel)52 BEGIN_EVENT_TABLE(ThemePrefs, PrefsPanel)
53    EVT_BUTTON(idLoadThemeCache,      ThemePrefs::OnLoadThemeCache)
54    EVT_BUTTON(idSaveThemeCache,      ThemePrefs::OnSaveThemeCache)
55    EVT_BUTTON(idLoadThemeComponents, ThemePrefs::OnLoadThemeComponents)
56    EVT_BUTTON(idSaveThemeComponents, ThemePrefs::OnSaveThemeComponents)
57    EVT_BUTTON(idReadThemeInternal,   ThemePrefs::OnReadThemeInternal)
58    EVT_BUTTON(idSaveThemeAsCode,     ThemePrefs::OnSaveThemeAsCode)
59 END_EVENT_TABLE()
60 
61 ThemePrefs::ThemePrefs(wxWindow * parent, wxWindowID winid)
62 /* i18n-hint: A theme is a consistent visual style across an application's
63  graphical user interface, including choices of colors, and similarity of images
64  such as those on button controls.  Audacity can load and save alternative
65  themes. */
66 :  PrefsPanel(parent, winid, XO("Theme"))
67 {
68    Populate();
69 }
70 
~ThemePrefs(void)71 ThemePrefs::~ThemePrefs(void)
72 {
73 }
74 
GetSymbol()75 ComponentInterfaceSymbol ThemePrefs::GetSymbol()
76 {
77    return THEME_PREFS_PLUGIN_SYMBOL;
78 }
79 
GetDescription()80 TranslatableString ThemePrefs::GetDescription()
81 {
82    return XO("Preferences for Theme");
83 }
84 
HelpPageName()85 ManualPageID ThemePrefs::HelpPageName()
86 {
87    return "Theme_Preferences";
88 }
89 
90 /// Creates the dialog and its contents.
Populate()91 void ThemePrefs::Populate()
92 {
93    // First any pre-processing for constructing the GUI.
94 
95    //------------------------- Main section --------------------
96    // Now construct the GUI itself.
97    // Use 'eIsCreatingFromPrefs' so that the GUI is
98    // initialised with values from gPrefs.
99    ShuttleGui S(this, eIsCreatingFromPrefs);
100    PopulateOrExchange(S);
101    // ----------------------- End of main section --------------
102 }
103 
104 /// Create the dialog contents, or exchange data with it.
PopulateOrExchange(ShuttleGui & S)105 void ThemePrefs::PopulateOrExchange(ShuttleGui & S)
106 {
107    S.SetBorder(2);
108    S.StartScroller();
109 
110    S.StartStatic(XO("Info"));
111    {
112       S.AddFixedText(
113          XO(
114 "Themability is an experimental feature.\n\nTo try it out, click \"Save Theme Cache\" then find and modify the images and colors in\nImageCacheVxx.png using an image editor such as the Gimp.\n\nClick \"Load Theme Cache\" to load the changed images and colors back into Audacity.\n\n(Only the Transport Toolbar and the colors on the wavetrack are currently affected, even\nthough the image file shows other icons too.)")
115          );
116 
117 #ifdef _DEBUG
118       S.AddFixedText(
119          Verbatim(
120 "This is a debug version of Audacity, with an extra button, 'Output Sourcery'. This will save a\nC version of the image cache that can be compiled in as a default.")
121          );
122 #endif
123 
124       S.AddFixedText(
125          XO(
126 "Saving and loading individual theme files uses a separate file for each image, but is\notherwise the same idea.")
127          );
128    }
129    S.EndStatic();
130 
131    /* i18n-hint: && in here is an escape character to get a single & on screen,
132     * so keep it as is */
133    S.StartStatic(		XO("Theme Cache - Images && Color"));
134    {
135       S.StartHorizontalLay(wxALIGN_LEFT);
136       {
137          S.Id(idSaveThemeCache).AddButton(XXO("Save Theme Cache"));
138          S.Id(idLoadThemeCache).AddButton(XXO("Load Theme Cache"));
139 
140          // This next button is only provided in Debug mode.
141          // It is for developers who are compiling Audacity themselves
142          // and who wish to generate a NEW ThemeAsCeeCode.h and compile it in.
143 #ifdef _DEBUG
144          S.Id(idSaveThemeAsCode).AddButton(Verbatim("Output Sourcery"));
145 #endif
146 
147          S.Id(idReadThemeInternal).AddButton(XXO("&Defaults"));
148       }
149       S.EndHorizontalLay();
150    }
151    S.EndStatic();
152 
153    // JKC: 'Ergonomic' details:
154    // Theme components are used much less frequently than
155    // the ImageCache.  Yet it's easy to click them 'by mistake'.
156    //
157    // To reduce that risk, we use a separate box to separate them off.
158    // And choose text on the buttons that is shorter, making the
159    // buttons smaller and less tempting to click.
160    S.StartStatic( XO("Individual Theme Files"),1);
161    {
162       S.StartHorizontalLay(wxALIGN_LEFT);
163       {
164          S.Id(idSaveThemeComponents).AddButton( XXO("Save Files"));
165          S.Id(idLoadThemeComponents).AddButton( XXO("Load Files"));
166       }
167       S.EndHorizontalLay();
168    }
169    S.EndStatic();
170    S.EndScroller();
171 
172 }
173 
174 /// Load Theme from multiple png files.
OnLoadThemeComponents(wxCommandEvent & WXUNUSED (event))175 void ThemePrefs::OnLoadThemeComponents(wxCommandEvent & WXUNUSED(event))
176 {
177    wxBusyCursor busy;
178    theTheme.LoadComponents();
179    ApplyUpdatedImages();
180 }
181 
182 /// Save Theme to multiple png files.
OnSaveThemeComponents(wxCommandEvent & WXUNUSED (event))183 void ThemePrefs::OnSaveThemeComponents(wxCommandEvent & WXUNUSED(event))
184 {
185    wxBusyCursor busy;
186    theTheme.SaveComponents();
187 }
188 
189 /// Load Theme from single png file.
OnLoadThemeCache(wxCommandEvent & WXUNUSED (event))190 void ThemePrefs::OnLoadThemeCache(wxCommandEvent & WXUNUSED(event))
191 {
192    wxBusyCursor busy;
193    theTheme.ReadImageCache();
194    ApplyUpdatedImages();
195 }
196 
197 /// Save Theme to single png file.
OnSaveThemeCache(wxCommandEvent & WXUNUSED (event))198 void ThemePrefs::OnSaveThemeCache(wxCommandEvent & WXUNUSED(event))
199 {
200    wxBusyCursor busy;
201    theTheme.CreateImageCache();
202    theTheme.WriteImageMap();// bonus - give them the html version.
203 }
204 
205 /// Read Theme from internal storage.
OnReadThemeInternal(wxCommandEvent & WXUNUSED (event))206 void ThemePrefs::OnReadThemeInternal(wxCommandEvent & WXUNUSED(event))
207 {
208    wxBusyCursor busy;
209    theTheme.ReadImageCache( theTheme.GetFallbackThemeType() );
210    ApplyUpdatedImages();
211 }
212 
213 /// Save Theme as C source code.
OnSaveThemeAsCode(wxCommandEvent & WXUNUSED (event))214 void ThemePrefs::OnSaveThemeAsCode(wxCommandEvent & WXUNUSED(event))
215 {
216    wxBusyCursor busy;
217    theTheme.SaveThemeAsCode();
218    theTheme.WriteImageDefs();// bonus - give them the Defs too.
219 }
220 
ApplyUpdatedImages()221 void ThemePrefs::ApplyUpdatedImages()
222 {
223    AColor::ReInit();
224 
225    wxCommandEvent e{ EVT_THEME_CHANGE };
226    wxTheApp->SafelyProcessEvent( e );
227 }
228 
229 /// Update the preferences stored on disk.
Commit()230 bool ThemePrefs::Commit()
231 {
232    ShuttleGui S(this, eIsSavingToPrefs);
233    PopulateOrExchange(S);
234 
235    return true;
236 }
237 
238 #ifdef EXPERIMENTAL_THEME_PREFS
239 namespace{
240 PrefsPanel::Registration sAttachment{ "Theme",
241    [](wxWindow *parent, wxWindowID winid, AudacityProject *)
__anon8c6cfe9c0202() 242    {
243       wxASSERT(parent); // to justify safenew
244       return safenew ThemePrefs(parent, winid);
245    },
246    false,
247    // Register with an explicit ordering hint because this one is
248    // only conditionally compiled
__anon8c6cfe9c0302() 249    { "", { Registry::OrderingHint::After, "Effects" } }
250 };
251 }
252 #endif
253