Define and use ShuttleGui::ConnectRoot...

... And corrected improper connections in HistoryWindow and ContrastDialog,
improper because they got called with the wrong this pointer, to
the control instead of the dialog.  But that was harmless anyway because the
handlers did not use this.
This commit is contained in:
Paul Licameli 2018-01-31 11:31:55 -05:00
parent d98e41aad1
commit 64a96e6f01
13 changed files with 115 additions and 56 deletions

View File

@ -96,16 +96,14 @@ HistoryWindow::HistoryWindow(AudacityProject *parent, UndoManager *manager):
S.StartMultiColumn(3, wxCENTRE);
{
mTotal = S.Id(ID_TOTAL).AddTextBox(_("&Total space used"), wxT("0"), 10);
mTotal->Bind(wxEVT_KEY_DOWN,
// ignore it
[](wxEvent&){});
mTotal = S.Id(ID_TOTAL)
.ConnectRoot(wxEVT_KEY_DOWN, &HistoryWindow::OnChar)
.AddTextBox(_("&Total space used"), wxT("0"), 10);
S.AddVariableText( {} )->Hide();
mAvail = S.Id(ID_AVAIL).AddTextBox(_("&Undo levels available"), wxT("0"), 10);
mAvail->Bind(wxEVT_KEY_DOWN,
// ignore it
[](wxEvent&){});
mAvail = S.Id(ID_AVAIL)
.ConnectRoot(wxEVT_KEY_DOWN, &HistoryWindow::OnChar)
.AddTextBox(_("&Undo levels available"), wxT("0"), 10);
S.AddVariableText( {} )->Hide();
S.AddPrompt(_("&Levels to discard"));
@ -122,10 +120,9 @@ HistoryWindow::HistoryWindow(AudacityProject *parent, UndoManager *manager):
/* i18n-hint: (verb)*/
mDiscard = S.Id(ID_DISCARD).AddButton(_("&Discard"));
mClipboard = S.AddTextBox(_("Clipboard space used"), wxT("0"), 10);
mClipboard->Bind(wxEVT_KEY_DOWN,
// ignore it
[](wxEvent&){});
mClipboard = S
.ConnectRoot(wxEVT_KEY_DOWN, &HistoryWindow::OnChar)
.AddTextBox(_("Clipboard space used"), wxT("0"), 10);
S.Id(ID_DISCARD_CLIPBOARD).AddButton(_("Discard"));
}
S.EndMultiColumn();
@ -164,6 +161,11 @@ HistoryWindow::HistoryWindow(AudacityProject *parent, UndoManager *manager):
parent->Bind(EVT_UNDO_RESET, &HistoryWindow::UpdateDisplay, this);
}
void HistoryWindow::OnChar( wxEvent& )
{
// ignore it
}
void HistoryWindow::OnAudioIO(wxCommandEvent& evt)
{
evt.Skip();

View File

@ -36,6 +36,7 @@ class HistoryWindow final : public wxDialogWrapper {
void DoUpdate();
void UpdateLevels();
void OnChar(wxEvent &event);
void OnSize(wxSizeEvent & event);
void OnCloseWindow(wxCloseEvent & WXUNUSED(event));
void OnItemSelected(wxListEvent & event);

View File

@ -578,10 +578,9 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
mEffects = S.Id(ID_List)
.Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES )
.ConnectRoot(wxEVT_KEY_DOWN,
&PluginRegistrationDialog::OnListChar)
.AddListControlReportMode({ _("Name"), _("State"), _("Path") });
mEffects->Bind(wxEVT_KEY_DOWN,
&PluginRegistrationDialog::OnListChar,
this);
#if wxUSE_ACCESSIBILITY
mEffects->SetAccessible(mAx = safenew CheckListAx(mEffects));
#endif

View File

@ -2083,6 +2083,9 @@ void ShuttleGuiBase::UpdateSizersCore(bool bPrepend, int Flags, bool prompt)
if (mItem.mDisabled)
mpWind->Enable( false );
for (auto &pair : mItem.mRootConnections)
mpWind->Connect( pair.first, pair.second, nullptr, mpDlg );
// Reset to defaults
mItem = {};
}

View File

@ -180,11 +180,36 @@ struct Item {
return std::move( *this );
}
// Dispatch events from the control to the dialog
// The template type deduction ensures consistency between the argument type
// and the event type. It does not (yet) ensure correctness of the type of
// the handler object.
template< typename Tag, typename Argument, typename Handler >
auto ConnectRoot(
wxEventTypeTag<Tag> eventType,
void (Handler::*func)(Argument&)
) &&
-> typename std::enable_if<
std::is_base_of<Argument, Tag>::value,
Item&&
>::type
{
mRootConnections.push_back({
eventType,
(void(wxEvtHandler::*)(wxEvent&)) (
static_cast<void(wxEvtHandler::*)(Argument&)>( func )
)
});
return std::move( *this );
}
std::function< void(wxWindow*) > mValidatorSetter;
TranslatableString mToolTip;
TranslatableString mName;
TranslatableString mNameSuffix;
std::vector<std::pair<wxEventType, wxObjectEventFunction>> mRootConnections;
long miStyle{};
bool mFocused { false };
@ -595,6 +620,24 @@ public:
return *this;
}
// Dispatch events from the control to the dialog
// The template type deduction ensures consistency between the argument type
// and the event type. It does not (yet) ensure correctness of the type of
// the handler object.
template< typename Tag, typename Argument, typename Handler >
auto ConnectRoot(
wxEventTypeTag<Tag> eventType,
void (Handler::*func)(Argument&)
)
-> typename std::enable_if<
std::is_base_of<Argument, Tag>::value,
ShuttleGui&
>::type
{
std::move( mItem ).ConnectRoot( eventType, func );
return *this;
}
// Prop() sets the proportion value, defined as in wxSizer::Add().
ShuttleGui & Prop( int iProp ){ ShuttleGuiBase::Prop(iProp); return *this;}; // Has to be here too, to return a ShuttleGui and not a ShuttleGuiBase.

View File

@ -87,6 +87,12 @@ SplashDialog::SplashDialog(wxWindow * parent)
Move( x, 60 );
}
void SplashDialog::OnChar(wxMouseEvent &event)
{
if ( event.ShiftDown() && event.ControlDown() )
wxLaunchDefaultBrowser("https://www.audacityteam.org");
}
void SplashDialog::Populate( ShuttleGui & S )
{
bool bShow;
@ -118,16 +124,11 @@ void SplashDialog::Populate( ShuttleGui & S )
wxDefaultPosition,
wxSize((int)(LOGOWITHNAME_WIDTH*fScale), (int)(LOGOWITHNAME_HEIGHT*fScale)));
S.Prop(0).AddWindow( icon );
S.Prop(0)
#if (0)
icon->Bind(wxEVT_LEFT_DOWN,
[this]( wxMouseEvent const & event ) ->void {
if ( event.ShiftDown() && event.ControlDown())
wxLaunchDefaultBrowser("https://www.audacityteam.org");
}
);
.ConnectRoot( wxEVT_LEFT_DOWN, &SplashDialog::OnChar)
#endif
.AddWindow( icon );
mpHtml = safenew LinkingHtmlWindow(S.GetParent(), -1,
wxDefaultPosition,

View File

@ -33,6 +33,7 @@ public:
private:
void OnChar(wxMouseEvent &event);
void Populate( ShuttleGui & S );
void OnDontShow( wxCommandEvent & Evt );

View File

@ -155,7 +155,7 @@ BEGIN_EVENT_TABLE(ContrastDialog,wxDialogWrapper)
EVT_BUTTON(wxID_CANCEL, ContrastDialog::OnClose)
END_EVENT_TABLE()
static void OnChar(wxKeyEvent & event)
void ContrastDialog::OnChar(wxKeyEvent &event)
{
// Is this still required?
if (event.GetKeyCode() == WXK_TAB) {
@ -252,8 +252,10 @@ ContrastDialog::ContrastDialog(wxWindow * parent, wxWindowID id,
.AddWindow(mForegroundEndT);
m_pButton_UseCurrentF = S.Id(ID_BUTTON_USECURRENTF).AddButton(_("&Measure selection"));
mForegroundRMSText=S.Id(ID_FOREGROUNDDB_TEXT).AddTextBox( {}, wxT(""), 17);
mForegroundRMSText->Bind(wxEVT_KEY_DOWN, OnChar);
mForegroundRMSText = S.Id(ID_FOREGROUNDDB_TEXT)
.ConnectRoot(wxEVT_KEY_DOWN,
&ContrastDialog::OnChar)
.AddTextBox( {}, wxT(""), 17);
//Background
S.AddFixedText(_("&Background:"));
@ -284,8 +286,10 @@ ContrastDialog::ContrastDialog(wxWindow * parent, wxWindowID id,
.AddWindow(mBackgroundEndT);
m_pButton_UseCurrentB = S.Id(ID_BUTTON_USECURRENTB).AddButton(_("Mea&sure selection"));
mBackgroundRMSText = S.Id(ID_BACKGROUNDDB_TEXT).AddTextBox( {}, wxT(""), 17);
mBackgroundRMSText->Bind(wxEVT_KEY_DOWN, OnChar);
mBackgroundRMSText = S.Id(ID_BACKGROUNDDB_TEXT)
.ConnectRoot(wxEVT_KEY_DOWN,
&ContrastDialog::OnChar)
.AddTextBox( {}, wxT(""), 17);
}
S.EndMultiColumn();
}
@ -300,16 +304,18 @@ ContrastDialog::ContrastDialog(wxWindow * parent, wxWindowID id,
S.AddFixedText(label.Translation());
mPassFailText = S.Id(ID_RESULTS_TEXT)
.Name(label)
.ConnectRoot(wxEVT_KEY_DOWN,
&ContrastDialog::OnChar)
.AddTextBox( {}, wxT(""), 50);
mPassFailText->Bind(wxEVT_KEY_DOWN, OnChar);
m_pButton_Reset = S.Id(ID_BUTTON_RESET).AddButton(_("R&eset"));
label = XO("&Difference:");
S.AddFixedText(label.Translation());
mDiffText = S.Id(ID_RESULTSDB_TEXT)
.Name(label)
.ConnectRoot(wxEVT_KEY_DOWN,
&ContrastDialog::OnChar)
.AddTextBox( {}, wxT(""), 50);
mDiffText->Bind(wxEVT_KEY_DOWN, OnChar);
m_pButton_Export = S.Id(ID_BUTTON_EXPORT).AddButton(_("E&xport..."));
}
S.EndMultiColumn();

View File

@ -54,6 +54,7 @@ public:
private:
// handlers
void OnChar(wxKeyEvent &event);
void OnGetURL(wxCommandEvent &event);
void OnExport(wxCommandEvent &event);
void OnGetForeground(wxCommandEvent & event);

View File

@ -864,12 +864,10 @@ void EffectEqualization::PopulateOrExchange(ShuttleGui & S)
mSliders[i] = safenew wxSliderWrapper(pParent, ID_Slider + i, 0, -20, +20,
wxDefaultPosition, wxSize(-1,150), wxSL_VERTICAL | wxSL_INVERSE);
mSliders[i]->Bind(wxEVT_ERASE_BACKGROUND,
// ignore it
[](wxEvent&){});
#if wxUSE_ACCESSIBILITY
mSliders[i]->SetAccessible(safenew SliderAx(mSliders[i], _("%d dB")));
#endif
mSlidersOld[i] = 0;
mEQVals[i] = 0.;
//S.SetSizerProportion(1);
@ -879,6 +877,8 @@ void EffectEqualization::PopulateOrExchange(ShuttleGui & S)
? wxString::Format(_("%d Hz"), (int)kThirdOct[i])
: wxString::Format(_("%g kHz"), kThirdOct[i]/1000.)
} )
.ConnectRoot(
wxEVT_ERASE_BACKGROUND, &EffectEqualization::OnErase)
.AddWindow( mSliders[i], wxEXPAND );
}
S.AddSpace(15,0);
@ -2757,6 +2757,10 @@ double EffectEqualization::splint(double x[], double y[], size_t n, double y2[],
return( a*y[k]+b*y[k+1]+((a*a*a-a)*y2[k]+(b*b*b-b)*y2[k+1])*h*h/6.);
}
void EffectEqualization::OnErase( wxEvent& )
{
}
void EffectEqualization::OnSize(wxSizeEvent & event)
{
mUIParent->Layout();

View File

@ -190,6 +190,7 @@ private:
void spline(double x[], double y[], size_t n, double y2[]);
double splint(double x[], double y[], size_t n, double y2[], double xr);
void OnErase( wxEvent &event );
void OnSize( wxSizeEvent & event );
void OnSlider( wxCommandEvent & event );
void OnInterp( wxCommandEvent & event );

View File

@ -226,14 +226,13 @@ void KeyConfigPrefs::PopulateOrExchange(ShuttleGui & S)
#endif
wxTE_PROCESS_ENTER);
mFilter->SetName(wxStripMenuCodes(mFilterLabel->GetLabel()));
mFilter->Bind(wxEVT_KEY_DOWN,
&KeyConfigPrefs::OnFilterKeyDown,
this);
mFilter->Bind(wxEVT_CHAR,
&KeyConfigPrefs::OnFilterChar,
this);
}
S.AddWindow(mFilter, wxALIGN_NOT | wxALIGN_LEFT);
S
.ConnectRoot(wxEVT_KEY_DOWN,
&KeyConfigPrefs::OnFilterKeyDown)
.ConnectRoot(wxEVT_CHAR,
&KeyConfigPrefs::OnFilterChar)
.AddWindow(mFilter, wxALIGN_NOT | wxALIGN_LEFT);
}
S.EndHorizontalLay();
}
@ -269,17 +268,15 @@ void KeyConfigPrefs::PopulateOrExchange(ShuttleGui & S)
mKey->SetAccessible(safenew WindowAccessible(mKey));
#endif
mKey->SetName(_("Short cut"));
mKey->Bind(wxEVT_KEY_DOWN,
&KeyConfigPrefs::OnHotkeyKeyDown,
this);
mKey->Bind(wxEVT_CHAR,
&KeyConfigPrefs::OnHotkeyChar,
this);
mKey->Bind(wxEVT_KILL_FOCUS,
&KeyConfigPrefs::OnHotkeyKillFocus,
this);
}
S.AddWindow(mKey);
S
.ConnectRoot(wxEVT_KEY_DOWN,
&KeyConfigPrefs::OnHotkeyKeyDown)
.ConnectRoot(wxEVT_CHAR,
&KeyConfigPrefs::OnHotkeyChar)
.ConnectRoot(wxEVT_KILL_FOCUS,
&KeyConfigPrefs::OnHotkeyKillFocus)
.AddWindow(mKey);
/* i18n-hint: (verb)*/
mSet = S.Id(SetButtonID).AddButton(_("&Set"));
@ -455,12 +452,12 @@ void KeyConfigPrefs::OnHotkeyKeyDown(wxKeyEvent & e)
t->SetValue(KeyEventToKeyString(e).Display());
}
void KeyConfigPrefs::OnHotkeyChar(wxKeyEvent & WXUNUSED(e))
void KeyConfigPrefs::OnHotkeyChar(wxEvent & WXUNUSED(e))
{
// event.Skip() not performed, so event will not be processed further.
}
void KeyConfigPrefs::OnHotkeyKillFocus(wxFocusEvent & e)
void KeyConfigPrefs::OnHotkeyKillFocus(wxEvent & e)
{
if (mKey->GetValue().empty() && mCommandSelected != wxNOT_FOUND) {
mKey->AppendText(mView->GetKey(mCommandSelected).Display());
@ -521,7 +518,7 @@ void KeyConfigPrefs::OnFilterKeyDown(wxKeyEvent & e)
}
}
void KeyConfigPrefs::OnFilterChar(wxKeyEvent & e)
void KeyConfigPrefs::OnFilterChar(wxEvent & e)
{
if (mViewType != ViewByKey)
{

View File

@ -58,12 +58,12 @@ private:
void OnSelected(wxCommandEvent & e);
void OnHotkeyKeyDown(wxKeyEvent & e);
void OnHotkeyChar(wxKeyEvent & e);
void OnHotkeyKillFocus(wxFocusEvent & e);
void OnHotkeyChar(wxEvent & e);
void OnHotkeyKillFocus(wxEvent & e);
void OnFilterTimer(wxTimerEvent & e);
void OnFilterKeyDown(wxKeyEvent & e);
void OnFilterChar(wxKeyEvent & e);
void OnFilterChar(wxEvent & e);
KeyView *mView;
wxTextCtrl *mKey;