diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index 4c93db8584..022b5e6fcf 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -37,6 +37,7 @@ #include "wx/apptrait.h" #include "wx/cmdline.h" #include "wx/msgout.h" +#include "wx/richmsgdlg.h" #include "wx/thread.h" #include "wx/vidmode.h" #include "wx/evtloop.h" @@ -457,56 +458,94 @@ wxRendererNative *wxGUIAppTraitsBase::CreateRenderer() bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) { #if wxDEBUG_LEVEL - // under MSW we prefer to use the base class version using ::MessageBox() - // even if wxMessageBox() is available because it has less chances to - // double fault our app than our wxMessageBox() + // If possible, show the assert using a dialog allowing to hide the stack + // trace by default to avoid frightening people unnecessarily. // - // under DFB the message dialog is not always functional right now + // Otherwise, show the assert using a basic message box, but under MSW + // we prefer to use the base class version using ::MessageBox() even if + // wxMessageBox() is available because it has less chances to double + // fault our app than our wxMessageBox() // - // and finally we can't use wxMessageBox() if it wasn't compiled in, of - // course -#if !defined(__WXMSW__) && !defined(__WXDFB__) && wxUSE_MSGDLG + // Notice that under DFB the message dialog is not always functional right + // now and, finally, we can't use wxMessageBox() if it wasn't compiled in. +#if wxUSE_RICHMSGDLG || \ + (wxUSE_MSGDLG && !defined(__WXMSW__) && !defined(__WXDFB__)) // we can't (safely) show the GUI dialog from another thread, only do it // for the asserts in the main thread if ( wxIsMainThread() ) { - wxString msgDlg = msg; + // Note that this and the other messages here are intentionally not + // translated -- they are for developpers only. + static const wxStringCharType* caption = wxS("wxWidgets Debug Alert"); -#if wxUSE_STACKWALKER - const wxString stackTrace = GetAssertStackTrace(); - if ( !stackTrace.empty() ) - msgDlg << wxT("\n\nCall stack:\n") << stackTrace; -#endif // wxUSE_STACKWALKER - - // this message is intentionally not translated -- it is for - // developpers only - msgDlg += wxT("\nDo you want to stop the program?\n") - wxT("You can also choose [Cancel] to suppress ") - wxT("further warnings."); + wxString msgDlg = wxS("A debugging check in this application ") + wxS("has failed.\n\n") + msg; // "No" button means to continue execution, so it should be the default // action as leaving the "Yes" button the default one would mean that // accidentally pressing Space or Enter would trap and kill the program. - switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"), - wxYES_NO | wxCANCEL | wxNO_DEFAULT | wxICON_STOP ) ) + const int flags = wxYES_NO | wxNO_DEFAULT | wxICON_STOP; + +#if wxUSE_STACKWALKER + const wxString stackTrace = GetAssertStackTrace(); +#endif // wxUSE_STACKWALKER + +#if wxUSE_RICHMSGDLG + wxRichMessageDialog dlg(NULL, msgDlg, caption, flags); + + dlg.SetYesNoLabels("Stop", "Continue"); + + dlg.ShowCheckBox("Don't show this dialog again"); + +#if wxUSE_STACKWALKER + if ( !stackTrace.empty() ) + dlg.ShowDetailedText(stackTrace); +#endif // wxUSE_STACKWALKER +#else // !wxUSE_RICHMSGDLG +#if wxUSE_STACKWALKER + if ( !stackTrace.empty() ) + msgDlg << wxT("\n\nCall stack:\n") << stackTrace; +#endif // wxUSE_STACKWALKER + + msgDlg += wxT("\nDo you want to stop the program?\n") + wxT("You can also choose [Cancel] to suppress ") + wxT("further warnings."); + + wxMessageDialog dlg(NULL, msg, caption, flags); +#endif // wxUSE_RICHMSGDLG/!wxUSE_RICHMSGDLG + + switch ( dlg.ShowModal() ) { - case wxYES: + case wxID_YES: // See the comment about using the same variable in // DoShowAssertDialog(). wxTrapInAssert = true; break; - case wxCANCEL: - // no more asserts + case wxID_CANCEL: + // This button is used with the plain message dialog only to + // indicate that no more assert dialogs should be shown, as + // there is no other way to do it with it. return true; - //case wxNO: nothing to do + case wxID_NO: +#if wxUSE_RICHMSGDLG + if ( dlg.IsCheckBoxChecked() ) + { + // With this dialog, the checkbox is used to indicate that + // the subsequent asserts should be skipped. + return true; + } +#endif // wxUSE_RICHMSGDLG + + // Nothing to do otherwise. + break; } return false; } -#endif // wxUSE_MSGDLG +#endif // wxUSE_RICHMSGDLG || wxUSE_MSGDLG #endif // wxDEBUG_LEVEL return wxAppTraitsBase::ShowAssertDialog(msg);