1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-04 17:49:45 +02:00

Bug 1403 - Message can now be displayed in multiple columns

Uses 'End-of-Transmission-Block' character to mark the column split(s)
and is defined as a static constant for ease of use.
This commit is contained in:
tip2tail 2016-08-30 20:29:10 +01:00 committed by Steve Daulton
parent ce09f4b883
commit 56b1f2d2cb
3 changed files with 155 additions and 135 deletions

View File

@ -550,19 +550,26 @@ int TimerRecordDialog::RunWaitDialog()
bool bIsRecording = true; bool bIsRecording = true;
wxString sPostAction = m_pTimerAfterCompleteChoiceCtrl->GetString(m_pTimerAfterCompleteChoiceCtrl->GetSelection()); wxString sPostAction = m_pTimerAfterCompleteChoiceCtrl->GetString(m_pTimerAfterCompleteChoiceCtrl->GetSelection());
wxString strMsg;
strMsg.Printf(_("Recording start:\t\t\t%s\n") + // Two column layout. Line spacing must match for both columns.
_("Duration:\t\t\t%s\n") + // First column
_("Recording end:\t\t\t%s\n\n") + wxString strMsg = wxString::Format(_("Recording start:\n") +
_("Automatic Save enabled:\t\t%s\n") + _("Duration:\n") +
_("Automatic Export enabled:\t\t%s\n") + _("Recording end:\n\n") +
_("Action after Timer Recording:\t%s"), _("Automatic Save enabled:\n") +
GetDisplayDate(m_DateTime_Start).c_str(), _("Automatic Export enabled:\n") +
m_TimeSpan_Duration.Format(), _("Action after Timer Recording:"));
GetDisplayDate(m_DateTime_End).c_str(),
(m_bAutoSaveEnabled ? _("Yes") : _("No")), strMsg += ProgressDialog::ColoumnSplitMarker;
(m_bAutoExportEnabled ? _("Yes") : _("No")),
sPostAction); // Second column
strMsg += wxString::Format(wxT("%s\n%s\n%s\n\n%s\n%s\n%s"),
GetDisplayDate(m_DateTime_Start).c_str(),
m_TimeSpan_Duration.Format(),
GetDisplayDate(m_DateTime_End).c_str(),
(m_bAutoSaveEnabled ? _("Yes") : _("No")),
(m_bAutoExportEnabled ? _("Yes") : _("No")),
sPostAction);
TimerProgressDialog TimerProgressDialog
progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(), progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(),
@ -833,7 +840,10 @@ void TimerRecordDialog::PopulateOrExchange(ShuttleGui& S)
safenew wxDatePickerCtrl(this, // wxWindow *parent, safenew wxDatePickerCtrl(this, // wxWindow *parent,
ID_DATEPICKER_END, // wxWindowID id, ID_DATEPICKER_END, // wxWindowID id,
m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime, m_DateTime_End); // const wxDateTime& dt = wxDefaultDateTime,
// const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDP_DEFAULT | wxDP_SHOWCENTURY, const wxValidator& validator = wxDefaultValidator, const wxString& name = "datectrl") // const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
// long style = wxDP_DEFAULT | wxDP_SHOWCENTURY,
// const wxValidator& validator = wxDefaultValidator,
// const wxString& name = "datectrl")
m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating. m_pDatePickerCtrl_End->SetRange(m_DateTime_Start, wxInvalidDateTime); // No backdating.
m_pDatePickerCtrl_End->SetName(_("End Date")); m_pDatePickerCtrl_End->SetName(_("End Date"));
#if wxUSE_ACCESSIBILITY #if wxUSE_ACCESSIBILITY
@ -1019,21 +1029,25 @@ int TimerRecordDialog::WaitForStart()
// MY: The Waiting For Start dialog now shows what actions will occur after recording has completed // MY: The Waiting For Start dialog now shows what actions will occur after recording has completed
wxString sPostAction = m_pTimerAfterCompleteChoiceCtrl->GetString(m_pTimerAfterCompleteChoiceCtrl->GetSelection()); wxString sPostAction = m_pTimerAfterCompleteChoiceCtrl->GetString(m_pTimerAfterCompleteChoiceCtrl->GetSelection());
/* i18n-hint: Time specifications like "Sunday 28th October 2007 15:16:17 GMT" // Two column layout. Line spacing must match for both columns.
* but hopefully translated by wxwidgets will be inserted into this */ // First column
wxString strMsg; wxString strMsg = wxString::Format(_("Waiting to start recording at:\n") +
strMsg.Printf(_("Waiting to start recording at:\t%s\n") + _("Recording duration:\n") +
_("Recording duration:\t\t%s\n") + _("Scheduled to stop at:\n\n") +
_("Scheduled to stop at:\t\t%s\n\n") + _("Automatic Save enabled:\n") +
_("Automatic Save enabled:\t\t%s\n") + _("Automatic Export enabled:\n") +
_("Automatic Export enabled:\t\t%s\n") + _("Action after Timer Recording:"));
_("Action after Timer Recording:\t%s"),
GetDisplayDate(m_DateTime_Start).c_str(), strMsg += ProgressDialog::ColoumnSplitMarker;
m_TimeSpan_Duration.Format(),
GetDisplayDate(m_DateTime_End).c_str(), // Second column
(m_bAutoSaveEnabled ? _("Yes") : _("No")), strMsg += wxString::Format(wxT("%s\n%s\n%s\n\n%s\n%s\n%s"),
(m_bAutoExportEnabled ? _("Yes") : _("No")), GetDisplayDate(m_DateTime_Start).c_str(),
sPostAction); m_TimeSpan_Duration.Format(),
GetDisplayDate(m_DateTime_End).c_str(),
(m_bAutoSaveEnabled ? _("Yes") : _("No")),
(m_bAutoExportEnabled ? _("Yes") : _("No")),
sPostAction);
wxDateTime startWait_DateTime = wxDateTime::UNow(); wxDateTime startWait_DateTime = wxDateTime::UNow();
wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime; wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime;
@ -1060,15 +1074,20 @@ int TimerRecordDialog::PreActionDelay(int iActionIndex, TimerRecordCompletedActi
wxString sCountdownLabel; wxString sCountdownLabel;
sCountdownLabel.Printf("%s in:", sAction); sCountdownLabel.Printf("%s in:", sAction);
// Build a clearer message... // Two column layout. Line spacing must match for both columns.
wxString sMessage; // First column
sMessage.Printf(_("Timer Recording completed.\n\n") + wxString strMsg = wxString::Format(_("Timer Recording completed.\n\n") +
_("Recording Saved:\t\t\t%s\n") + _("Recording Saved:\n") +
_("Recording Exported:\t\t%s\n") + _("Recording Exported:\n") +
_("Action after Timer Recording:\t%s"), _("Action after Timer Recording:"));
((eCompletedActions & TR_ACTION_SAVED) ? _("Yes") : _("No")),
((eCompletedActions & TR_ACTION_EXPORTED) ? _("Yes") : _("No")), strMsg += ProgressDialog::ColoumnSplitMarker;
sAction);
// Second column
strMsg += wxString::Format(wxT("\n\n%s\n%s\n%s"),
((eCompletedActions & TR_ACTION_SAVED) ? _("Yes") : _("No")),
((eCompletedActions & TR_ACTION_EXPORTED) ? _("Yes") : _("No")),
sAction);
wxDateTime dtNow = wxDateTime::UNow(); wxDateTime dtNow = wxDateTime::UNow();
wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0); wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
@ -1076,7 +1095,7 @@ int TimerRecordDialog::PreActionDelay(int iActionIndex, TimerRecordCompletedActi
TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(), TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
_("Audacity Timer Record - Waiting"), _("Audacity Timer Record - Waiting"),
sMessage, strMsg,
pdlgHideStopButton | pdlgHideElapsedTime, pdlgHideStopButton | pdlgHideElapsedTime,
sCountdownLabel); sCountdownLabel);

View File

@ -29,6 +29,8 @@
#include "../Audacity.h" #include "../Audacity.h"
#include "../MemoryX.h" #include "../MemoryX.h"
#include <algorithm>
#include <wx/defs.h> #include <wx/defs.h>
#include <wx/app.h> #include <wx/app.h>
#include <wx/button.h> #include <wx/button.h>
@ -1066,6 +1068,27 @@ void ProgressDialog::Init()
#endif #endif
} }
// Add a new text column each time this is called.
void ProgressDialog::AddMessageAsColumn(wxBoxSizer * pSizer, const wxString & sText) {
// Assuming that we don't want empty columns, bail out if there is no text.
if (sText.IsEmpty())
{
return;
}
// Create a statictext object and add to the sizer
wxStaticText* oText = safenew wxStaticText(this,
wxID_ANY,
sText,
wxDefaultPosition,
wxDefaultSize,
wxALIGN_LEFT);
oText->SetName(sText); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
pSizer->Add(oText, 1, wxEXPAND | wxALL, 5);
}
bool ProgressDialog::Create(const wxString & title, bool ProgressDialog::Create(const wxString & title,
const wxString & message /* = wxEmptyString */, const wxString & message /* = wxEmptyString */,
int flags /* = pdlgDefaultFlags */, int flags /* = pdlgDefaultFlags */,
@ -1089,70 +1112,63 @@ bool ProgressDialog::Create(const wxString & title,
{ {
return false; return false;
} }
SetName(GetTitle());
wxWindow *w; SetName(GetTitle()); // This was added for NVDA screen reader and may now be redundant.
wxSize ds; SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT); // Ancient code. Is it still required?
SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
wxFlexGridSizer *g;
wxBoxSizer *h;
{ {
auto v = std::make_unique<wxBoxSizer>(wxVERTICAL); wxWindow *window;
wxArrayString arMessages(wxSplit(message, ProgressDialog::ColoumnSplitMarker));
mMessage = safenew wxStaticText(this, // There may be more than one column, so create a BoxSizer container
wxID_ANY, auto uColSizer = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
message, //wxBoxSizer * pColSizer = safenew wxBoxSizer(wxHORIZONTAL);
wxDefaultPosition, auto colSizer = uColSizer.get();
wxDefaultSize,
wxALIGN_LEFT); for (size_t column = 0; column < arMessages.GetCount(); column++) {
mMessage->SetName(message); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs) AddMessageAsColumn(colSizer, arMessages[column]);
v->Add(mMessage, 1, wxEXPAND | wxALL, 10); }
ds.y += mMessage->GetSize().y + 20;
// and put message column(s) into a main vertical sizer.
auto vertSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
vertSizer->Add(uColSizer.release(), 1, wxEXPAND | wxALL, 10);
//
//
//
mGauge = safenew wxGauge(this, mGauge = safenew wxGauge(this,
wxID_ANY, wxID_ANY,
1000, 1000,
wxDefaultPosition, wxDefaultPosition,
wxDefaultSize, wxDefaultSize,
wxGA_HORIZONTAL); wxGA_HORIZONTAL);
v->Add(mGauge, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10); vertSizer->Add(mGauge, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
ds.y += mGauge->GetSize().y + 10;
//
//
//
{ {
auto ug = std::make_unique<wxFlexGridSizer>(2, 2, 10, 10); auto uGridSizer = std::make_unique<wxFlexGridSizer>(2, 2, 10, 10);
// MY: Only one row if we are not going to show the elapsed time // Only one row if we are not going to show the elapsed time
if (m_bShowElapsedTime == false) { if (m_bShowElapsedTime == false) {
ug = std::make_unique<wxFlexGridSizer>(1, 2, 10, 10); uGridSizer = std::make_unique<wxFlexGridSizer>(1, 2, 10, 10);
} }
g = ug.get(); auto gridSizer = uGridSizer.get();
if (m_bShowElapsedTime) { if (m_bShowElapsedTime) {
w = safenew wxStaticText(this, window = safenew wxStaticText(this,
wxID_ANY, wxID_ANY,
_("Elapsed Time:"), _("Elapsed Time:"),
wxDefaultPosition, wxDefaultPosition,
wxDefaultSize, wxDefaultSize,
wxALIGN_RIGHT); wxALIGN_RIGHT);
w->SetName(w->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
g->Add(w, 0, wxALIGN_RIGHT); window->SetName(window->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
gridSizer->Add(window, 0, wxALIGN_RIGHT);
mElapsed = safenew wxStaticText(this, mElapsed = safenew wxStaticText(this,
wxID_ANY, wxID_ANY,
wxT("00:00:00"), wxT("00:00:00"),
wxDefaultPosition, wxDefaultPosition,
wxDefaultSize, wxDefaultSize,
wxALIGN_LEFT); wxALIGN_LEFT);
mElapsed->SetName(mElapsed->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs) mElapsed->SetName(mElapsed->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
g->Add(mElapsed, 0, wxALIGN_LEFT); gridSizer->Add(mElapsed, 0, wxALIGN_LEFT);
ds.y += mElapsed->GetSize().y + 10;
} }
// Customised "Remaining" label text // Customised "Remaining" label text
@ -1161,73 +1177,53 @@ bool ProgressDialog::Create(const wxString & title,
sRemainingText = _("Remaining Time:"); sRemainingText = _("Remaining Time:");
} }
// window = safenew wxStaticText(this,
// wxID_ANY,
// sRemainingText,
w = safenew wxStaticText(this, wxDefaultPosition,
wxID_ANY, wxDefaultSize,
sRemainingText, wxALIGN_RIGHT);
wxDefaultPosition, window->SetName(window->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
wxDefaultSize, gridSizer->Add(window, 0, wxALIGN_RIGHT);
wxALIGN_RIGHT);
w->SetName(w->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
g->Add(w, 0, wxALIGN_RIGHT);
mRemaining = safenew wxStaticText(this, mRemaining = safenew wxStaticText(this,
wxID_ANY, wxID_ANY,
wxT("00:00:00"), wxT("00:00:00"),
wxDefaultPosition, wxDefaultPosition,
wxDefaultSize, wxDefaultSize,
wxALIGN_LEFT); wxALIGN_LEFT);
mRemaining->SetName(mRemaining->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs) mRemaining->SetName(mRemaining->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
g->Add(mRemaining, 0, wxALIGN_LEFT); gridSizer->Add(mRemaining, 0, wxALIGN_LEFT);
v->Add(ug.release(), 0, wxALIGN_CENTER | wxLEFT | wxRIGHT | wxBOTTOM, 10); vertSizer->Add(uGridSizer.release(), 0, wxALIGN_CENTER | wxLEFT | wxRIGHT | wxBOTTOM, 10);
} }
ds.y += mRemaining->GetSize().y + 10;
{ {
auto uh = std::make_unique<wxBoxSizer>(wxHORIZONTAL); auto uButtonBar = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
h = uh.get(); auto buttonBarSizer = uButtonBar.get();
if (!(flags & pdlgHideStopButton)) if (!(flags & pdlgHideStopButton)) {
{ window = safenew wxButton(this, wxID_OK, _("Stop"));
w = safenew wxButton(this, wxID_OK, _("Stop")); buttonBarSizer->Add(window, 0, wxRIGHT, 10);
h->Add(w, 0, wxRIGHT, 10);
} }
if (!(flags & pdlgHideCancelButton)) {
if (!(flags & pdlgHideCancelButton)) window = safenew wxButton(this, wxID_CANCEL, _("Cancel"));
{ buttonBarSizer->Add(window, 0, wxRIGHT, 10);
w = safenew wxButton(this, wxID_CANCEL, _("Cancel"));
h->Add(w, 0, wxRIGHT, 10);
} }
vertSizer->Add(uButtonBar.release(), 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 10);
v->Add(uh.release(), 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 10);
} }
SetSizer(v.release()); SetSizerAndFit(vertSizer.release());
} }
Layout(); Layout();
ds.x = wxMax(g->GetSize().x, h->GetSize().x) + 10;
ds.y += w->GetSize().y + 10;
wxClientDC dc(this); wxClientDC dc(this);
dc.GetMultiLineTextExtent(message, &mLastW, &mLastH); dc.GetMultiLineTextExtent(message, &mLastW, &mLastH);
// MY: Add a little bit more width when we have TABs to stop words wrapping // Add a little bit more width when we have TABs to stop words wrapping
int iTabFreq = wxMax((message.Freq('\t') - 1), 0); int iTabFreq = wxMax((message.Freq('\t') - 1), 0);
mLastW = mLastW + (iTabFreq * 8); mLastW = mLastW + (iTabFreq * 8);
#if defined(__WXMAC__)
mMessage->SetMinSize(wxSize(mLastW, mLastH));
#endif
// The 300 really isn't needed, but it keeps it at a decent width.
ds.x = wxMax(wxMax(wxMax(ds.x, mLastW) + 20, wxMax(ds.y, mLastH)), 300);
SetClientSize(ds);
Centre(wxCENTER_FRAME | wxBOTH); Centre(wxCENTER_FRAME | wxBOTH);
mStartTime = wxGetLocalTimeMillis().GetValue(); mStartTime = wxGetLocalTimeMillis().GetValue();
@ -1551,7 +1547,7 @@ void ProgressDialog::Beep() const
} }
} }
// MY: Confirm action taken by user. // Confirm action taken by user.
// Returns TRUE if the user confirms Yes // Returns TRUE if the user confirms Yes
bool ProgressDialog::ConfirmAction(const wxString & sPrompt, bool ProgressDialog::ConfirmAction(const wxString & sPrompt,
const wxString & sTitle, const wxString & sTitle,

View File

@ -78,6 +78,9 @@ public:
int Update(int current, int total, const wxString & message = wxEmptyString); int Update(int current, int total, const wxString & message = wxEmptyString);
void SetMessage(const wxString & message); void SetMessage(const wxString & message);
// 'ETB' character to indicate a new column in the message text.
static const wxChar ColoumnSplitMarker = (char)23;
protected: protected:
wxWindow *mHadFocus; wxWindow *mHadFocus;
@ -110,6 +113,8 @@ private:
const wxString & sTitle, const wxString & sTitle,
int iButtonID = -1); int iButtonID = -1);
void AddMessageAsColumn(wxBoxSizer * pSizer, const wxString & sText);
private: private:
// This guarantees we have an active event loop...possible during OnInit() // This guarantees we have an active event loop...possible during OnInit()
wxEventLoopGuarantor mLoop; wxEventLoopGuarantor mLoop;