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 "ErrorDialog.h"
14#ifdef HAS_SENTRY_REPORTING
15#include "ErrorReportDialog.h"
16#endif
17#include "AudacityMessageBox.h"
18#include "ProgressDialog.h"
19#include "MultiDialog.h"
20#include <wx/app.h>
21#include <wx/progdlg.h>
22#include <wx/windowptr.h>
23#include <wx/utils.h>
24
25using namespace BasicUI;
26
28
30{
31 wxTheApp->CallAfter(action);
32}
33
35{
36 wxTheApp->Yield();
37}
38
40 const BasicUI::WindowPlacement &placement,
41 const TranslatableString &dlogTitle,
42 const TranslatableString &message,
43 const ManualPageID &helpPage,
44 const BasicUI::ErrorDialogOptions &options)
45{
46 using namespace BasicUI;
47 bool modal = true;
48 auto parent = wxWidgetsWindowPlacement::GetParent(placement);
49 switch (options.type) {
50 case ErrorDialogType::ModalErrorReport: {
51#ifdef HAS_SENTRY_REPORTING
52 ErrorReportDialog dlog(parent, dlogTitle, message, helpPage,
53 options.log, modal);
54
55 dlog.CentreOnParent();
56 dlog.ShowModal();
57 return;
58#else
59 break;
60#endif
61 }
62 case ErrorDialogType::ModelessError: {
63 if (!parent)
64 parent = wxTheApp->GetTopWindow();
65 // To be nonmodal, either it needs a parent, to avoid leaks, or it must
66 // guarantee eventual deletion of itself. There might be no top window
67 // on MacOS. Let's just force it to be modal in that case.
68 if (parent)
69 modal = false;
70 break;
71 }
72 default:
73 break;
74 }
75 auto pDlog = Destroy_ptr<ErrorDialog>( safenew ErrorDialog{ parent,
76 dlogTitle, message, helpPage, options.log,
77 options.modalHelp, modal } );
78 pDlog->CentreOnParent();
79 if (modal)
80 pDlog->ShowModal();
81 else {
82 pDlog->Show();
83 pDlog.release(); // not a memory leak, because it has a parent
84 }
85}
86
89 const TranslatableString &message,
90 MessageBoxOptions options)
91{
92 // Compute the style argument to pass to wxWidgets
93 long style = 0;
94 switch (options.iconStyle) {
95 case Icon::Warning :
96 style = wxICON_WARNING;
97 break;
98 case Icon::Error :
99 style = wxICON_ERROR;
100 break;
101 case Icon::Question :
102 style = wxICON_QUESTION;
103 break;
104 case Icon::Information :
105 style = wxICON_INFORMATION;
106 break;
107 default:
108 break;
109 }
110 switch (options.buttonStyle) {
111 case Button::Ok :
112 style |= wxOK;
113 break;
114 case Button::YesNo :
115 style |= wxYES_NO;
116 break;
117 default:
118 break;
119 }
120 if (!options.yesOrOkDefaultButton && options.buttonStyle == Button::YesNo)
121 style |= wxNO_DEFAULT;
122 if (options.cancelButton)
123 style |= wxCANCEL;
124 if (options.centered)
125 style |= wxCENTER;
126
127 // Preserving the default style AudacityMessageBox had,
128 // when none of the above were explicitly specified
129 if (!style)
130 style = wxOK | wxCENTRE;
131
132 // This calls through to ::wxMessageBox:
133 auto wxResult =
134 ::AudacityMessageBox(message, options.caption, style,
135 options.parent
137 : nullptr);
138 // This switch exhausts all possibilities for the return from::wxMessageBox.
139 // see utilscmn.cpp in wxWidgets.
140 // Remap to our toolkit-neutral enumeration.
141 switch (wxResult) {
142 case wxYES:
143 return MessageBoxResult::Yes;
144 case wxNO:
145 return MessageBoxResult::No;
146 case wxOK:
147 return MessageBoxResult::Ok;
148 case wxCANCEL:
149 return MessageBoxResult::Cancel;
150 case wxHELP:
151 // should not happen, because we don't ever pass wxHELP
152 default:
153 wxASSERT(false);
154 return MessageBoxResult::None;
155 }
156}
157
158std::unique_ptr<BasicUI::ProgressDialog>
160 const TranslatableString &message,
161 unsigned flags,
162 const TranslatableString &remainingLabelText)
163{
164 unsigned options = 0;
165 if (!(flags & ProgressShowStop))
166 options |= pdlgHideStopButton;
167 if (!(flags & ProgressShowCancel))
168 options |= pdlgHideCancelButton;
169 if ((flags & ProgressHideTime))
170 options |= pdlgHideElapsedTime;
171 if ((flags & ProgressConfirmStopOrCancel))
172 options |= pdlgConfirmStopCancel;
173 // Usually wxWindow objects should not be managed by std::unique_ptr
174 // See https://docs.wxwidgets.org/3.0/overview_windowdeletion.html
175 // But on macOS the use of wxWindowPtr for the progress dialog sometimes
176 // causes hangs.
177 return std::make_unique<::ProgressDialog>(
178 title, message, options, remainingLabelText);
179}
180
181namespace {
182struct MyGenericProgress : wxGenericProgressDialog, GenericProgressDialog {
184 const TranslatableString &message,
185 wxWindow *parent = nullptr,
187 : wxGenericProgressDialog{
188 title.Translation(), message.Translation(),
189 300000, // range
190 parent,
191 style
192 }
193 {}
194 ~MyGenericProgress() override = default;
196 {
197 if (wxGenericProgressDialog::Pulse())
199 else if (WasCancelled())
201 else
203 }
204};
205}
206
207std::unique_ptr<GenericProgressDialog>
209 const BasicUI::WindowPlacement &placement,
211 const TranslatableString &message,
212 int style)
213{
214 // Compute the style argument to pass to wxWidgets
215 int flags = 0;
216 if ((style & ProgressCanAbort))
217 flags |= wxPD_CAN_ABORT;
218 if ((style & ProgressAppModal))
219 flags |= wxPD_APP_MODAL;
221 flags |= wxPD_ELAPSED_TIME;
222 if ((style & ProgressSmooth))
223 flags |= wxPD_SMOOTH;
224
225 return std::make_unique<MyGenericProgress>(
226 title, message, wxWidgetsWindowPlacement::GetParent(placement), flags);
227}
228
231 const TranslatableStrings &buttons,
232 const ManualPageID &helpPage,
233 const TranslatableString &boxMsg, bool log)
234{
235 return ::ShowMultiDialog(message, title, buttons, helpPage, boxMsg, log);
236}
237
239{
240 return wxLaunchDefaultBrowser(url);
241}
242
243std::unique_ptr<BasicUI::WindowPlacement> wxWidgetsBasicUI::DoFindFocus()
244{
245 return std::make_unique<wxWidgetsWindowPlacement>(wxWindow::FindFocus());
246}
247
249{
250 auto pWindow = wxWidgetsWindowPlacement::GetParent(focus);
251 pWindow->SetFocus();
252}
253
255{
256 return wxLayout_RightToLeft == wxTheApp->GetLayoutDirection();
257}
258
260{
261 return wxIsMainThread();
262}
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:164
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:186
Subclasses may hold information such as a parent window pointer for a dialog.
Definition: BasicUI.h:30
Gives an Error message with an option for help.
Definition: ErrorDialog.h:26
A dialog, that has "Send", "Don't send" and help buttons.
Holds a msgid for the translation catalog; may also bind format arguments.
std::unique_ptr< BasicUI::GenericProgressDialog > DoMakeGenericProgress(const BasicUI::WindowPlacement &placement, const TranslatableString &title, const TranslatableString &message, int style) override
bool IsUiThread() const override
void DoCallAfter(const BasicUI::Action &action) override
bool DoOpenInDefaultBrowser(const wxString &url) override
BasicUI::MessageBoxResult DoMessageBox(const TranslatableString &message, BasicUI::MessageBoxOptions options) override
void DoSetFocus(const BasicUI::WindowPlacement &focus) 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::ProgressDialog > DoMakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags, const TranslatableString &remainingLabelText) override
bool IsUsingRtlLayout() const override
std::unique_ptr< BasicUI::WindowPlacement > DoFindFocus() 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:155
@ ProgressHideTime
Definition: BasicUI.h:143
@ ProgressShowCancel
Definition: BasicUI.h:142
@ ProgressConfirmStopOrCancel
Definition: BasicUI.h:144
@ ProgressShowStop
Definition: BasicUI.h:141
int ShowMultiDialog(const TranslatableString &message, const TranslatableString &title, const TranslatableStrings &buttons, const ManualPageID &helpPage, const TranslatableString &boxMsg, bool log)
Display a dialog with radio buttons.
Definition: BasicUI.h:367
std::function< void()> Action
Definition: BasicUI.h:24
MessageBoxResult
Definition: BasicUI.h:132
@ ProgressCanAbort
Definition: BasicUI.h:148
@ ProgressShowElapsedTime
Definition: BasicUI.h:150
@ ProgressSmooth
Definition: BasicUI.h:151
@ ProgressAppModal
Definition: BasicUI.h:149
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:383
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:52
ErrorDialogType type
Type of help dialog.
Definition: BasicUI.h:70
std::wstring log
Optional extra logging information to be shown.
Definition: BasicUI.h:74
bool modalHelp
Whether the secondary help dialog with more information should be modal.
Definition: BasicUI.h:72
TranslatableString caption
Definition: BasicUI.h:124
WindowPlacement * parent
Definition: BasicUI.h:123
ProgressResult Pulse() override
Give some visual indication of progress. Call only on the main thread.
MyGenericProgress(const TranslatableString &title, const TranslatableString &message, wxWindow *parent=nullptr, int style=ProgressAppModal|ProgressShowElapsedTime|ProgressSmooth)
static wxWindow * GetParent(const WindowPlacement &placement)
Retrieve the pointer to window, if placement is of this type; else null.
Implementation of BasicUI using wxWidgets.