From c5d4360fc99a0b9bd512e9dc19087c96dc669345 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Fri, 6 Sep 2013 17:09:20 +0000 Subject: [PATCH] Add lambda-friendly wxDialog::ShowWindowModalThenDo(). Add a convenience ShowWindowModalThenDo() variant of ShowWindowModal() that takes a functor argument and calls it when the dialog is closed. This is, of course, particularly useful when the argument is a C++11 lambda, especially when having more than one window-modal dialog invoked from the same window, which can get messy quickly with all the wxEVT_WINDOW_MODAL_DIALOG_CLOSED handlers. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74775 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dialog.h | 40 ++++++++++++++++++++++++++++++++++++++++ interface/wx/dialog.h | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/include/wx/dialog.h b/include/wx/dialog.h index 95e6b6f..e32cabb 100644 --- a/include/wx/dialog.h +++ b/include/wx/dialog.h @@ -79,6 +79,11 @@ public: virtual void ShowWindowModal () ; virtual void SendWindowModalDialogEvent ( wxEventType type ); +#ifdef wxHAS_EVENT_BIND + template + void ShowWindowModalThenDo(const Functor& onEndModal); +#endif // wxHAS_EVENT_BIND + // Modal dialogs have a return code - usually the id of the last // pressed button void SetReturnCode(int returnCode) { m_returnCode = returnCode; } @@ -391,5 +396,40 @@ typedef void (wxEvtHandler::*wxWindowModalDialogEventFunction)(wxWindowModalDial #define EVT_WINDOW_MODAL_DIALOG_CLOSED(winid, func) \ wx__DECLARE_EVT1(wxEVT_WINDOW_MODAL_DIALOG_CLOSED, winid, wxWindowModalDialogEventHandler(func)) +#ifdef wxHAS_EVENT_BIND +template +class wxWindowModalDialogEventFunctor +{ +public: + wxWindowModalDialogEventFunctor(const Functor& f) + : m_f(f), m_wasCalled(false) + {} + + void operator()(wxWindowModalDialogEvent& event) + { + if ( m_wasCalled ) + { + event.Skip(); + return; + } + + m_wasCalled = true; + m_f(event.GetReturnCode()); + } + +private: + Functor m_f; + bool m_wasCalled; +}; + +template +void wxDialogBase::ShowWindowModalThenDo(const Functor& onEndModal) +{ + Bind(wxEVT_WINDOW_MODAL_DIALOG_CLOSED, + wxWindowModalDialogEventFunctor(onEndModal)); + ShowWindowModal(); +}; +#endif // wxHAS_EVENT_BIND + #endif // _WX_DIALOG_H_BASE_ diff --git a/interface/wx/dialog.h b/interface/wx/dialog.h index cf330bc..b578adb 100644 --- a/interface/wx/dialog.h +++ b/interface/wx/dialog.h @@ -596,7 +596,8 @@ public: @return The value set with SetReturnCode(). - @see ShowWindowModal(), EndModal(), GetReturnCode(), SetReturnCode() + @see ShowWindowModal(), ShowWindowModalThenDo(), + EndModal(), GetReturnCode(), SetReturnCode() */ virtual int ShowModal(); @@ -614,11 +615,51 @@ public: the other platforms it behaves like ShowModal() (but also sends the above mentioned event). - @see wxWindowModalDialogEvent + @see wxWindowModalDialogEvent, ShowWindowModalThenDo() @since 2.9.0 */ void ShowWindowModal(); + + /** + Shows a dialog modal to the parent top level window only and call a + functor after the dialog is closed. + + Same as the other ShowWindowModal() overload, but calls the functor + passed as the argument upon completion, instead of generating the + wxEVT_WINDOW_MODAL_DIALOG_CLOSED event. + + This form is particularly useful in combination with C++11 lambdas, + when it allows writing window-modal very similarly to how ShowModal() + is used (with the notable exception of not being able to create + the dialog on stack): + + @code + wxWindowPtr dlg(new wxMessageDialog(this, "Hello!")); + + dlg->ShowWindowModalThenDo([this,dlg](int retcode){ + if ( retcode == wxID_OK ) + DoSomething(); + // dlg is implicitly destroyed here, because the pointer was + // explicitly captured by the lambda + }); + @endcode + + @param onEndModal Function object to call when the dialog is + closed. The functor is called with a single + integer argument, dialog's return code. + + @note The dialog instance must not be destroyed until @a onEndModal + is called. The best way to ensure thay is to use wxWindowPtr + to hold a pointer and include it in the lambda's capture, + by value (not reference!), as shown in the example above. + + @since 3.0 + + @see wxWindowPtr + */ + template + void ShowWindowModalThenDo(const Functor& onEndModal); }; -- 2.7.4