Audacity 3.2.0
HelpSystem.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 HelpSystem.cpp
6
7 Jimmy Johnson
8 Leland Lucius
9 Richard Ash
10
11 was merged with LinkingHtmlWindow.h
12
13 Vaughan Johnson
14 Dominic Mazzoni
15
16 utility fn and
17 descendant of HtmlWindow that opens links in the user's
18 default browser
19
20*//********************************************************************/
21
22
23#include "HelpSystem.h"
24
25#include <wx/setup.h> // for wxUSE_* macros
26#include <wx/frame.h>
27#include <wx/icon.h>
28#include <wx/log.h>
29#include <wx/stattext.h>
30#include <wx/textctrl.h>
31#include <wx/html/htmlwin.h>
32#include <wx/settings.h>
33#include <wx/statusbr.h>
34#include <wx/regex.h>
35
36#include "FileNames.h"
37#include "AllThemeResources.h"
38#include "ShuttleGui.h"
39#include "Theme.h"
40#include "HelpText.h"
41#include "Prefs.h"
42#include "wxFileNameWrapper.h"
43
44#include "BasicUI.h"
45
46const wxString HelpSystem::HelpHostname = wxT("manual.audacityteam.org");
47const wxString HelpSystem::HelpServerHomeDir = wxT("/");
48const wxString HelpSystem::HelpServerManDir = wxT("/man/");
49
50const wxString HelpSystem::LocalHelpManDir = wxT("/man/");
51
52namespace {
53
54// Helper class to make browser "simulate" a modal dialog
56{
57public:
58 HtmlTextHelpDialog(wxWindow *pParent, const TranslatableString &title)
59 : BrowserDialog{ pParent, title }
60 {
61#if !wxCHECK_VERSION(3, 0, 0)
62 MakeModal( true );
63#endif
64 }
66 {
67#if !wxCHECK_VERSION(3, 0, 0)
68 MakeModal( false );
69#endif
70 // On Windows, for some odd reason, the Audacity window will be sent to
71 // the back. So, make sure that doesn't happen.
72 GetParent()->Raise();
73 }
74};
75
76}
77
81void HelpSystem::ShowInfoDialog( wxWindow *parent,
82 const TranslatableString &dlogTitle,
83 const TranslatableString &shortMsg,
84 const wxString &message,
85 const int xSize, const int ySize)
86{
87 wxDialogWrapper dlog(parent, wxID_ANY,
88 dlogTitle,
89 wxDefaultPosition, wxDefaultSize,
90 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX /*| wxDEFAULT_FRAME_STYLE */);
91
92 dlog.SetName();
93 ShuttleGui S(&dlog, eIsCreating);
94
95 S.StartVerticalLay(1);
96 {
97 S.AddTitle( shortMsg );
98 S.Style( wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH | wxTE_RICH2 |
99 wxTE_AUTO_URL | wxTE_NOHIDESEL | wxHSCROLL | wxTE_PROCESS_ENTER)
100 .AddTextWindow(message)
101 ->Bind(wxEVT_TEXT_ENTER, [&dlog](auto&) {
102 dlog.EndModal(wxID_OK);
103 });
104
105 S.SetBorder( 0 );
106 S.StartHorizontalLay(wxALIGN_CENTER_HORIZONTAL, 0);
107 S.AddStandardButtons(eOkButton);
108 S.EndHorizontalLay();
109 }
110 S.EndVerticalLay();
111
112 // Smallest size is half default size. Seems reasonable.
113 dlog.SetMinSize( wxSize(xSize/2, ySize/2) );
114 dlog.SetSize( wxSize(xSize, ySize) );
115 dlog.Center();
116 dlog.ShowModal();
117}
118
119void HelpSystem::ShowHtmlText(wxWindow *pParent,
120 const TranslatableString &Title,
121 const wxString &HtmlText,
122 bool bIsFile,
123 bool bModal)
124{
125 LinkingHtmlWindow *html;
126
127 wxASSERT(pParent); // to justify safenew
128 // JKC: ANSWER-ME: Why do we create a fake 'frame' and then put a BrowserDialog
129 // inside it, rather than have a variant of the BrowserDialog that is a
130 // frame??
131 // Bug 1412 seems to be related to the extra frame.
132 auto pFrame = safenew wxFrame {
133 pParent, wxID_ANY, Title.Translation(), wxDefaultPosition, wxDefaultSize,
134#if defined(__WXMAC__)
135 // On OSX, the html frame can go behind the help dialog and if the help
136 // html frame is modal, you can't get back to it. Pressing escape gets
137 // you out of this, but it's just easier to add the wxSTAY_ON_TOP flag
138 // to prevent it from falling behind the dialog. Not the perfect solution
139 // but acceptable in this case.
140 wxSTAY_ON_TOP |
141#endif
142 wxDEFAULT_FRAME_STYLE
143 };
144
145 BrowserDialog * pWnd;
146 if( bModal )
147 pWnd = safenew HtmlTextHelpDialog{ pFrame, Title };
148 else
149 pWnd = safenew BrowserDialog{ pFrame, Title };
150
151 // Bug 1412 workaround for 'extra window'. Hide the 'fake' window.
152 pFrame->SetTransparent(0);
153 ShuttleGui S( pWnd, eIsCreating );
154
155 S.Style( wxNO_BORDER | wxTAB_TRAVERSAL )
156 .Prop(true)
157 .StartPanel();
158 {
159 S.StartHorizontalLay( wxEXPAND, false );
160 {
161 S.Id( wxID_BACKWARD )
162 .Disable()
163#if wxUSE_TOOLTIPS
164 .ToolTip( XO("Backwards" ) )
165#endif
166 /* i18n-hint arrowhead meaning backward movement */
167 .AddButton( XXO("<") );
168 S.Id( wxID_FORWARD )
169 .Disable()
170#if wxUSE_TOOLTIPS
171 .ToolTip( XO("Forwards" ) )
172#endif
173 /* i18n-hint arrowhead meaning forward movement */
174 .AddButton( XXO(">") );
175 }
176 S.EndHorizontalLay();
177
178 html = safenew LinkingHtmlWindow(S.GetParent(), wxID_ANY,
179 wxDefaultPosition,
180 bIsFile ? wxSize(500, 400) : wxSize(480, 240),
181 wxHW_SCROLLBAR_AUTO);
182
183 html->SetRelatedFrame( pFrame, wxT("Help: %s") );
184 if( bIsFile )
185 html->LoadFile( HtmlText );
186 else
187 html->SetPage( HtmlText);
188
189 S.Prop(1).Focus().Position( wxEXPAND )
190 .AddWindow( html );
191
192 S.Id( wxID_CANCEL ).AddButton( XXO("Close"), wxALIGN_CENTER, true );
193 }
194 S.EndPanel();
195
196 // -- START of ICON stuff -----
197 // If this section (providing an icon) causes compilation errors on linux, comment it out for now.
198 // it will just mean that the icon is missing. Works OK on Windows.
199 #ifdef __WXMSW__
200 wxIcon ic{ wxICON(AudacityLogo) };
201 #else
202 wxIcon ic{};
203 ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
204 #endif
205 pFrame->SetIcon( ic );
206 // -- END of ICON stuff -----
207
208
209 pWnd->mpHtml = html;
210 pWnd->SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
211
212 pFrame->CreateStatusBar();
213 pFrame->Centre();
214 pFrame->Layout();
215 pFrame->SetSizeHints(pWnd->GetSize());
216
217 pFrame->SetName(Title.Translation());
218 if (bModal)
219 pWnd->ShowModal();
220 else {
221 pWnd->Show(true);
222 pFrame->Show(true);
223 }
224
225 html->SetRelatedStatusBar( 0 );
226
227 return;
228}
229
230// Shows help in browser, or possibly in own dialog.
231void HelpSystem::ShowHelp(wxWindow *parent,
232 const FilePath &localFileName,
233 const URLString &remoteURL,
234 bool bModal,
235 bool alwaysDefaultBrowser)
236{
237 wxASSERT(parent); // to justify safenew
238 wxString HelpMode = wxT("Local"); //this probably always gets overwritten to FromInternet
239 //TODO: remove code which handles local manual
240
241 gPrefs->Read(wxT("/GUI/Help"), &HelpMode, {"FromInternet"} );
242
243 {
244 // these next lines are for legacy cfg files (pre 2.0) where we had different modes
245 if( (HelpMode == wxT("Standard")) || (HelpMode == wxT("InBrowser")) )
246 {
247 HelpMode = GUIManualLocation.Default().Internal();
248 GUIManualLocation.Write(HelpMode);
249 gPrefs->Flush();
250 }
251 }
252
253 // Anchors (URLs with a '#' in them) are not supported by many OSs for local file names
254 // See, for example, https://groups.google.com/forum/#!topic/wx-users/pC0uOZJalRQ
255 // Problems have been reported on Win, Mac and some versions of Linux.
256 // So we set HelpMode to use the internet if an anchor is found.
257 if (localFileName.Find('#', true) != wxNOT_FOUND)
258 HelpMode = wxT("FromInternet");
259 // Until a solution is found for this, the next few lines are irrelevant.
260
261 // Obtain the local file system file name, without the anchor if present.
262 wxString localfile;
263 if (localFileName.Find('#', true) != wxNOT_FOUND)
264 localfile = localFileName.BeforeLast('#');
265 else
266 localfile = localFileName;
267
268 if( (HelpMode == wxT("FromInternet")) && !remoteURL.empty() )
269 {
270 // Always go to remote URL. Use External browser.
271 OpenInDefaultBrowser( remoteURL );
272 }
273 else if( localfile.empty() || !wxFileExists( localfile ))
274 {
275 if (remoteURL.empty())
276 {
277 // If you give an empty remote URL, you should have already ensured
278 // that the file exists!
279 wxASSERT(!remoteURL.empty());
280 // I can't find it'.
281 // Use Built-in browser to suggest you use the remote url.
282 wxString Text = HelpText(wxT("remotehelp"));
283 Text.Replace(wxT("*URL*"), remoteURL.GET());
284 // Always make the 'help on the internet' dialog modal.
285 // Fixes Bug 1411.
286 ShowHtmlText(parent, XO("Help on the Internet"), Text, false, true);
287 }
288 else
289 {
290 // Use External browser to go to remote URL.
291 OpenInDefaultBrowser(remoteURL);
292 }
293 }
294 else if( HelpMode == wxT("Local") || alwaysDefaultBrowser)
295 {
296 // Local file, External browser
297 OpenInDefaultBrowser( L"file:" + localFileName );
298 }
299 else
300 {
301 // Local file, Built-in browser
302 ShowHtmlText( parent, {}, localFileName, true, bModal );
303 }
304}
305
306void HelpSystem::ShowHelp(wxWindow *parent,
307 const ManualPageID &PageName,
308 bool bModal)
309{
312 const wxString ReleaseSuffix = L".html";
313
314 FilePath localHelpPage;
315 wxString webHelpPath;
316 wxString webHelpPage;
317 wxString releasePageName;
318 wxString anchor; // optional part of URL after (and including) the '#'
319 const auto &PageNameStr = PageName.GET();
320 if (PageNameStr.Find('#', true) != wxNOT_FOUND)
321 { // need to split anchor off into separate variable
322 releasePageName = PageNameStr.BeforeLast('#');
323 anchor = wxT("#") + PageNameStr.AfterLast('#');
324 }
325 else
326 {
327 releasePageName = PageName.GET();
328 anchor = wxT("");
329 }
330 // The wiki pages are transformed to static HTML by
331 // scripts/mw2html_audacity/mw2html.py
332 // The name is first transformed to lower case, then all
333 // 'special characters' are replaced by underscores. Spaces are
334 // transformed to "+".
335 //
336 // The transformations are handled in mw2html by first applying
337 // 'urllib.parse.quote_plus' (escape chars that are not in "always safe" list)
338 // then replacing escape characters (%xx) with underscores,
339 // and finally removing duplicate / redundant underscores.
340 //
341 // The front page and 'quick_help' are treated as special cases and placed in
342 // the root of the help directory rather than the "/man/" sub-directory.
343 if (releasePageName == L"Main_Page")
344 {
345 releasePageName = L"index" + ReleaseSuffix + anchor;
346 localHelpPage = wxFileName(FileNames::HtmlHelpDir(), releasePageName).GetFullPath();
347 webHelpPath = L"https://" + HelpSystem::HelpHostname + HelpSystem::HelpServerHomeDir;
348 }
349 else if (releasePageName == L"Quick_Help")
350 {
351 releasePageName = L"quick_help" + ReleaseSuffix + anchor;
352 localHelpPage = wxFileName(FileNames::HtmlHelpDir(), releasePageName).GetFullPath();
353 webHelpPath = L"https://" + HelpSystem::HelpHostname + HelpSystem::HelpServerHomeDir;
354 }
355 // not a page name, but rather a full path (e.g. to wiki)
356 // in which case do not do any substitutions.
357 else if (releasePageName.StartsWith( "http" ) )
358 {
359 localHelpPage = "";
360 releasePageName += anchor;
361 // webHelpPath remains empty
362 }
363 else
364 {
365 // Handle all other pages.
366 // Change to lower case.
367 releasePageName = releasePageName.Lower();
368 wxRegEx re;
369 // replace 'special characters' with underscores.
370 // RFC 2396 defines the characters a-z, A-Z, 0-9 and ".-_" as "always safe"
371 // mw2html also replaces "-" with "_" so replace that too.
372
373 // If PageName contains a %xx code, mw2html will transform it:
374 // '%xx' => '%25xx' => '_'
375 re.Compile(wxT("%.."));
376 re.ReplaceAll(&releasePageName, (wxT("_")));
377 // Now replace all other 'not-safe' characters.
378 re.Compile(wxT("[^[:alnum:] . [:space:]]"));
379 re.ReplaceAll(&releasePageName, (wxT("_")));
380 // Replace spaces with "+"
381 releasePageName.Replace(wxT(" "), wxT("+"), true);
382 // Reduce multiple underscores to single underscores
383 re.Compile(wxT("__+"));
384 re.ReplaceAll(&releasePageName, (wxT("_")));
385 // Replace "_." with "."
386 releasePageName.Replace(wxT("_."), wxT("."), true);
387 // Concatenate file name with file extension and anchor.
388 releasePageName = releasePageName + ReleaseSuffix + anchor;
389 // Other than index and quick_help, all local pages are in subdirectory 'LocalHelpManDir'.
390 localHelpPage = wxFileName(FileNames::HtmlHelpDir() + LocalHelpManDir, releasePageName).GetFullPath();
391 // Other than index and quick_help, all on-line pages are in subdirectory 'HelpServerManDir'.
392 webHelpPath = L"https://" + HelpSystem::HelpHostname + HelpSystem::HelpServerManDir;
393 }
394
395 webHelpPage = webHelpPath + releasePageName;
396
397
398 wxLogMessage(wxT("Help button pressed: PageName %s, releasePageName %s"),
399 PageName.GET(), releasePageName);
400 wxLogMessage(wxT("webHelpPage %s, localHelpPage %s"),
401 webHelpPage, localHelpPage);
402
403 wxASSERT(parent); // to justify safenew
404
406 parent,
407 localHelpPage,
408 webHelpPage,
409 bModal
410 );
411}
412
413// For compilers that support precompilation, includes "wx/wx.h".
414#include <wx/wxprec.h>
415
416#include <wx/mimetype.h>
417#include <wx/filename.h>
418#include <wx/uri.h>
419
420BEGIN_EVENT_TABLE(BrowserDialog, wxDialogWrapper)
424 EVT_KEY_DOWN(BrowserDialog::OnKeyDown)
426
427
429 : wxDialogWrapper{ pParent, ID, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER /*| wxMAXIMIZE_BOX */ }
430{
431 int width, height;
432 const int minWidth = 400;
433 const int minHeight = 250;
434
435 gPrefs->Read(wxT("/GUI/BrowserWidth"), &width, minWidth);
436 gPrefs->Read(wxT("/GUI/BrowserHeight"), &height, minHeight);
437
438 if (width < minWidth || width > wxSystemSettings::GetMetric(wxSYS_SCREEN_X))
439 width = minWidth;
440 if (height < minHeight || height > wxSystemSettings::GetMetric(wxSYS_SCREEN_Y))
441 height = minHeight;
442
443 SetMinSize(wxSize(minWidth, minHeight));
444 SetSize(wxDefaultPosition.x, wxDefaultPosition.y, width, height, wxSIZE_AUTO);
445}
446
447void BrowserDialog::OnForward(wxCommandEvent & WXUNUSED(event))
448{
449 mpHtml->HistoryForward();
451}
452
453void BrowserDialog::OnBackward(wxCommandEvent & WXUNUSED(event))
454{
455 mpHtml->HistoryBack();
457}
458
459void BrowserDialog::OnClose(wxCommandEvent & WXUNUSED(event))
460{
461 if (IsModal() && !mDismissed)
462 {
463 mDismissed = true;
464 EndModal(wxID_CANCEL);
465 }
466 auto parent = GetParent();
467
468 gPrefs->Write(wxT("/GUI/BrowserWidth"), GetSize().GetX());
469 gPrefs->Write(wxT("/GUI/BrowserHeight"), GetSize().GetY());
470 gPrefs->Flush();
471
472#ifdef __WXMAC__
473 auto grandparent = GetParent()->GetParent();
474#endif
475
476 parent->Destroy();
477
478#ifdef __WXMAC__
479 if(grandparent && grandparent->IsShown()) {
480 grandparent->Raise();
481 }
482#endif
483}
484
485void BrowserDialog::OnKeyDown(wxKeyEvent & event)
486{
487 bool bSkip = true;
488 if (event.GetKeyCode() == WXK_ESCAPE)
489 {
490 bSkip = false;
491 Close(false);
492 }
493 event.Skip(bSkip);
494}
495
496
498{
499 wxWindow * pWnd;
500 if( (pWnd = FindWindowById( wxID_BACKWARD, this )) != NULL )
501 {
502 pWnd->Enable(mpHtml->HistoryCanBack());
503 }
504 if( (pWnd = FindWindowById( wxID_FORWARD, this )) != NULL )
505 {
506 pWnd->Enable(mpHtml->HistoryCanForward());
507 }
508}
509
511{
512 wxURI uri(link.GET());
513 BasicUI::OpenInDefaultBrowser(uri.BuildURI());
514}
515
516LinkingHtmlWindow::LinkingHtmlWindow(wxWindow *parent, wxWindowID id /*= -1*/,
517 const wxPoint& pos /*= wxDefaultPosition*/,
518 const wxSize& size /*= wxDefaultSize*/,
519 long style /*= wxHW_SCROLLBAR_AUTO*/) :
520 HtmlWindow(parent, id, pos, size, style)
521{
522}
523
524void LinkingHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
525{
526 wxString href = link.GetHref();
527
528 if( href.StartsWith( wxT("innerlink:help:")))
529 {
530 HelpSystem::ShowHelp(this, ManualPageID{ href.Mid( 15 ) }, true );
531 return;
532 }
533 else if( href.StartsWith(wxT("innerlink:")) )
534 {
535 wxString FileName =
536 wxFileName( FileNames::HtmlHelpDir(), href.Mid( 10 ) + wxT(".htm") ).GetFullPath();
537 if( wxFileExists( FileName ) )
538 {
539 HelpSystem::ShowHelp(this, FileName, wxEmptyString, false);
540 return;
541 }
542 else
543 {
544 SetPage( HelpText( href.Mid( 10 )));
545 wxGetTopLevelParent(this)->SetLabel( TitleText( href.Mid( 10 )).Translation() );
546 }
547 }
548 else if( href.StartsWith(wxT("mailto:")) || href.StartsWith(wxT("file:")) )
549 {
550 OpenInDefaultBrowser( link.GetHref() );
551 return;
552 }
553 else if( !href.StartsWith( wxT("http:")) && !href.StartsWith( wxT("https:")) )
554 {
555 HtmlWindow::OnLinkClicked( link );
556 }
557 else
558 {
559 OpenInDefaultBrowser(link.GetHref());
560 return;
561 }
562 wxFrame * pFrame = GetRelatedFrame();
563 if( !pFrame )
564 return;
565 wxWindow * pWnd = pFrame->FindWindow(BrowserDialog::ID);
566 if( !pWnd )
567 return;
568 BrowserDialog * pDlg = wxDynamicCast( pWnd , BrowserDialog );
569 if( !pDlg )
570 return;
571 pDlg->UpdateButtons();
572}
573
575 wxT("/GUI/Help"),
576 {
577 ByColumns,
578 { XO("Local") , XO("From Internet") , },
579 { wxT("Local") , wxT("FromInternet") , }
580 },
581 1 // "FromInternet"
582};
583
wxT("CloseDown"))
Toolkit-neutral facade for basic user interface services.
END_EVENT_TABLE()
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
void OpenInDefaultBrowser(const URLString &link)
Definition: HelpSystem.cpp:510
ChoiceSetting GUIManualLocation
Definition: HelpSystem.cpp:574
TranslatableString TitleText(const wxString &Key)
Definition: HelpText.cpp:127
wxString HelpText(const wxString &Key)
Definition: HelpText.cpp:238
#define safenew
Definition: MemoryX.h:10
static const auto title
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
ByColumns_t ByColumns
Definition: Prefs.cpp:515
wxString FilePath
Definition: Project.h:21
@ eIsCreating
Definition: ShuttleGui.h:37
@ eOkButton
Definition: ShuttleGui.h:609
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
int id
Adds some event handling to an HtmlWindow.
Definition: HelpSystem.h:140
void UpdateButtons()
Definition: HelpSystem.cpp:497
void OnClose(wxCommandEvent &event)
Definition: HelpSystem.cpp:459
void OnKeyDown(wxKeyEvent &event)
Definition: HelpSystem.cpp:485
void OnBackward(wxCommandEvent &event)
Definition: HelpSystem.cpp:453
HtmlWindow * mpHtml
Definition: HelpSystem.h:154
void OnForward(wxCommandEvent &event)
Definition: HelpSystem.cpp:447
bool Write(const wxString &value)
Definition: Prefs.cpp:424
const EnumValueSymbol & Default() const
Definition: Prefs.cpp:380
const wxString & Internal() const
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:231
static const wxString LocalHelpManDir
Definition: HelpSystem.h:111
static void ShowInfoDialog(wxWindow *parent, const TranslatableString &dlogTitle, const TranslatableString &shortMsg, const wxString &message, const int xSize, const int ySize)
Displays cuttable information in a text ctrl, with an OK button.
Definition: HelpSystem.cpp:81
static const wxString HelpHostname
Definition: HelpSystem.h:96
static const wxString HelpServerHomeDir
Definition: HelpSystem.h:101
static const wxString HelpServerManDir
Definition: HelpSystem.h:106
static void ShowHtmlText(wxWindow *pParent, const TranslatableString &Title, const wxString &HtmlText, bool bIsFile=false, bool bModal=false)
Definition: HelpSystem.cpp:119
HtmlWindow Class.
Definition: HtmlWindow.h:37
bool empty() const
Definition: Identifier.h:61
const wxString & GET() const
Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct...
Definition: Identifier.h:66
An HtmlWindow that handles linked clicked - usually the link will go to our own local copy of the man...
Definition: HelpSystem.h:126
LinkingHtmlWindow(wxWindow *parent, wxWindowID id=-1, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxHW_SCROLLBAR_AUTO)
Definition: HelpSystem.cpp:516
void OnLinkClicked(const wxHtmlLinkInfo &link) override
Definition: HelpSystem.cpp:524
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
Template generates different TaggedIdentifier classes that don't interconvert implicitly.
Definition: Identifier.h:113
wxBitmap & Bitmap(int iIndex)
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
HtmlTextHelpDialog(wxWindow *pParent, const TranslatableString &title)
Definition: HelpSystem.cpp:58
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
void SetName(const TranslatableString &title)
bool OpenInDefaultBrowser(const wxString &url)
Open an URL in default browser.
Definition: BasicUI.cpp:246
FILES_API FilePath HtmlHelpDir()