Audacity 3.2.0
wxWidgetsBasicUI.cpp
Go to the documentation of this file.
1/*!********************************************************************
2
3Audacity: A Digital Audio Editor
4
5@file wxWidgetsBasicUI.cpp
6
7Paul Licameli
8
9**********************************************************************/
10#include "wxWidgetsBasicUI.h"
12#include "MemoryX.h" // for Destroy_ptr
13#include "widgets/ErrorDialog.h"
14#ifdef HAS_SENTRY_REPORTING
16#endif
18#include "ProgressDialog.h"
19#include "MultiDialog.h"
20#include <wx/app.h>
21#include <wx/progdlg.h>
22#include <wx/windowptr.h>
23
24using namespace BasicUI;
25
27
29{
30 wxTheApp->CallAfter(action);
31}
32
34{
35 wxTheApp->Yield();
36}
37
39 const BasicUI::WindowPlacement &placement,
40 const TranslatableString &dlogTitle,
41 const TranslatableString &message,
42 const ManualPageID &helpPage,
43 const BasicUI::ErrorDialogOptions &options)
44{
45 using namespace BasicUI;
46 bool modal = true;
47 auto parent = wxWidgetsWindowPlacement::GetParent(placement);
48 switch (options.type) {
49 case ErrorDialogType::ModalErrorReport: {
50#ifdef HAS_SENTRY_REPORTING
51 ErrorReportDialog dlog(parent, dlogTitle, message, helpPage,
52 options.log, modal);
53
54 dlog.CentreOnParent();
55 dlog.ShowModal();
56 return;
57#else
58 break;
59#endif
60 }
61 case ErrorDialogType::ModelessError: {
62 if (!parent)
63 parent = wxTheApp->GetTopWindow();
64 // To be nonmodal, either it needs a parent, to avoid leaks, or it must
65 // guarantee eventual deletion of itself. There might be no top window
66 // on MacOS. Let's just force it to be modal in that case.
67 if (parent)
68 modal = false;
69 break;
70 }
71 default:
72 break;
73 }
74 auto pDlog = Destroy_ptr<ErrorDialog>( safenew ErrorDialog{ parent,
75 dlogTitle, message, helpPage, options.log,
76 options.modalHelp, modal } );
77 pDlog->CentreOnParent();
78 if (modal)
79 pDlog->ShowModal();
80 else {
81 pDlog->Show();
82 pDlog.release(); // not a memory leak, because it has a parent
83 }
84}
85
88 const TranslatableString &message,
89 MessageBoxOptions options)
90{
91 // Compute the style argument to pass to wxWidgets
92 long style = 0;
93 switch (options.iconStyle) {
94 case Icon::Warning :
95 style = wxICON_WARNING;
96 break;
97 case Icon::Error :
98 style = wxICON_ERROR;
99 break;
100 case Icon::Question :
101 style = wxICON_QUESTION;
102 break;
103 case Icon::Information :
104 style = wxICON_INFORMATION;
105 break;
106 default:
107 break;
108 }
109 switch (options.buttonStyle) {
110 case Button::Ok :
111 style |= wxOK;
112 break;
113 case Button::YesNo :
114 style |= wxYES_NO;
115 break;
116 default:
117 break;
118 }
119 if (!options.yesOrOkDefaultButton && options.buttonStyle == Button::YesNo)
120 style |= wxNO_DEFAULT;
121 if (options.cancelButton)
122 style |= wxCANCEL;
123 if (options.centered)
124 style |= wxCENTER;
125
126 // Preserving the default style AudacityMessageBox had,
127 // when none of the above were explicitly specified
128 if (!style)
129 style = wxOK | wxCENTRE;
130
131 // This calls through to ::wxMessageBox:
132 auto wxResult =
133 ::AudacityMessageBox(message, options.caption, style,
134 options.parent
136 : nullptr);
137 // This switch exhausts all possibilities for the return from::wxMessageBox.
138 // see utilscmn.cpp in wxWidgets.
139 // Remap to our toolkit-neutral enumeration.
140 switch (wxResult) {
141 case wxYES:
142 return MessageBoxResult::Yes;
143 case wxNO:
144 return MessageBoxResult::No;
145 case wxOK:
146 return MessageBoxResult::Ok;
147 case wxCANCEL:
148 return MessageBoxResult::Cancel;
149 case wxHELP:
150 // should not happen, because we don't ever pass wxHELP
151 default:
152 wxASSERT(false);
153 return MessageBoxResult::None;
154 }
155}
156
157namespace {
159 using ::ProgressDialog::ProgressDialog;
160 ~MyProgressDialog() override = default;
162 unsigned long long numerator,
163 unsigned long long denominator,
164 const TranslatableString &message) override
165 {
166 return Update(numerator, denominator, message);
167 }
168 virtual void SetMessage(const TranslatableString & message) override
169 {
171 }
172};
173}
174
175std::unique_ptr<BasicUI::ProgressDialog>
177 const TranslatableString &message,
178 unsigned flags,
179 const TranslatableString &remainingLabelText)
180{
181 unsigned options = 0;
182 if (~(flags & ProgressShowStop))
183 options |= pdlgHideStopButton;
184 if (~(flags & ProgressShowCancel))
185 options |= pdlgHideCancelButton;
186 if ((flags & ProgressHideTime))
187 options |= pdlgHideElapsedTime;
188 if ((flags & ProgressConfirmStopOrCancel))
189 options |= pdlgConfirmStopCancel;
190 // Usually wxWindow objects should not be managed by std::unique_ptr
191 // See https://docs.wxwidgets.org/3.0/overview_windowdeletion.html
192 // But on macOS the use of wxWindowPtr for the progress dialog sometimes
193 // causes hangs.
194 return std::make_unique<MyProgressDialog>(
195 title, message, options, remainingLabelText);
196}
197
198namespace {
199struct MyGenericProgress : wxGenericProgressDialog, GenericProgressDialog {
201 const TranslatableString &message,
202 wxWindow *parent = nullptr)
203 : wxGenericProgressDialog{
204 title.Translation(), message.Translation(),
205 300000, // range
206 parent,
207 wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_SMOOTH
208 }
209 {}
210 ~MyGenericProgress() override = default;
211 void Pulse() override { wxGenericProgressDialog::Pulse(); }
212};
213}
214
215std::unique_ptr<GenericProgressDialog>
217 const BasicUI::WindowPlacement &placement,
219 const TranslatableString &message)
220{
221 return std::make_unique<MyGenericProgress>(
222 title, message, wxWidgetsWindowPlacement::GetParent(placement));
223}
224
227 const TranslatableStrings &buttons,
228 const ManualPageID &helpPage,
229 const TranslatableString &boxMsg, bool log)
230{
231 return ::ShowMultiDialog(message, title, buttons, helpPage, boxMsg, log);
232}
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
#define safenew
Definition: MemoryX.h:10
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:162
int ShowMultiDialog(const TranslatableString &message, const TranslatableString &title, const TranslatableStrings &buttons, const ManualPageID &helpPage, const TranslatableString &boxMsg, bool log)
static const auto title
@ pdlgConfirmStopCancel
@ pdlgHideStopButton
@ pdlgHideElapsedTime
@ pdlgHideCancelButton
std::vector< TranslatableString > TranslatableStrings
Abstraction of a progress dialog with undefined time-to-completion estimate.
Definition: BasicUI.h:170
Abstraction of a progress dialog with well defined time-to-completion estimate.
Definition: BasicUI.h:154
Subclasses may hold information such as a parent window pointer for a dialog.
Definition: BasicUI.h:29
Gives an Error message with an option for help.
Definition: ErrorDialog.h:26
A dialog, that has "Send", "Don't send" and help buttons.
void SetMessage(const TranslatableString &message)
Holds a msgid for the translation catalog; may also bind format arguments.
void DoCallAfter(const BasicUI::Action &action) override
BasicUI::MessageBoxResult DoMessageBox(const TranslatableString &message, BasicUI::MessageBoxOptions options) override
int DoMultiDialog(const TranslatableString &message, const TranslatableString &title, const TranslatableStrings &buttons, const ManualPageID &helpPage, const TranslatableString &boxMsg, bool log) override
~wxWidgetsBasicUI() override
std::unique_ptr< BasicUI::GenericProgressDialog > DoMakeGenericProgress(const BasicUI::WindowPlacement &placement, const TranslatableString &title, const TranslatableString &message) override
std::unique_ptr< BasicUI::ProgressDialog > DoMakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags, const TranslatableString &remainingLabelText) override
void DoYield() override
void DoShowErrorDialog(const BasicUI::WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const BasicUI::ErrorDialogOptions &options) override
ProgressResult
Definition: BasicUI.h:145
@ ProgressHideTime
Definition: BasicUI.h:140
@ ProgressShowCancel
Definition: BasicUI.h:139
@ ProgressConfirmStopOrCancel
Definition: BasicUI.h:141
@ ProgressShowStop
Definition: BasicUI.h:138
std::function< void()> Action
Definition: BasicUI.h:24
MessageBoxResult
Definition: BasicUI.h:129
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:49
ErrorDialogType type
Type of help dialog.
Definition: BasicUI.h:67
std::wstring log
Optional extra logging information to be shown.
Definition: BasicUI.h:71
bool modalHelp
Whether the secondary help dialog with more information should be modal.
Definition: BasicUI.h:69
TranslatableString caption
Definition: BasicUI.h:121
WindowPlacement * parent
Definition: BasicUI.h:120
void Pulse() override
Give some visual indication of progress. Call only on the main thread.
MyGenericProgress(const TranslatableString &title, const TranslatableString &message, wxWindow *parent=nullptr)
ProgressResult Poll(unsigned long long numerator, unsigned long long denominator, const TranslatableString &message) override
Update the bar and poll for clicks. Call only on the main thread.
virtual void SetMessage(const TranslatableString &message) override
Change an existing dialog's message.
static wxWindow * GetParent(const WindowPlacement &placement)
Retrieve the pointer to window, if placement is of this type; else null.
Implementation of BasicUI using wxWidgets.