Use wxRichMessageDialog for showing assertion failures
This allows to hide the long (and possibly not fitting on the screen) call stack by default to avoid intimidating people not used to it and provides a much more clear way to ignore the subsequent asserts, by clicking a dedicated checkbox instead of having to choose the "Cancel" button which didn't make much sense. See #15430.
This commit is contained in:
@@ -37,6 +37,7 @@
|
|||||||
#include "wx/apptrait.h"
|
#include "wx/apptrait.h"
|
||||||
#include "wx/cmdline.h"
|
#include "wx/cmdline.h"
|
||||||
#include "wx/msgout.h"
|
#include "wx/msgout.h"
|
||||||
|
#include "wx/richmsgdlg.h"
|
||||||
#include "wx/thread.h"
|
#include "wx/thread.h"
|
||||||
#include "wx/vidmode.h"
|
#include "wx/vidmode.h"
|
||||||
#include "wx/evtloop.h"
|
#include "wx/evtloop.h"
|
||||||
@@ -457,56 +458,94 @@ wxRendererNative *wxGUIAppTraitsBase::CreateRenderer()
|
|||||||
bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg)
|
bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg)
|
||||||
{
|
{
|
||||||
#if wxDEBUG_LEVEL
|
#if wxDEBUG_LEVEL
|
||||||
// under MSW we prefer to use the base class version using ::MessageBox()
|
// If possible, show the assert using a dialog allowing to hide the stack
|
||||||
// even if wxMessageBox() is available because it has less chances to
|
// trace by default to avoid frightening people unnecessarily.
|
||||||
// double fault our app than our wxMessageBox()
|
|
||||||
//
|
//
|
||||||
// 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
|
// Notice that under DFB the message dialog is not always functional right
|
||||||
// course
|
// now and, finally, we can't use wxMessageBox() if it wasn't compiled in.
|
||||||
#if !defined(__WXMSW__) && !defined(__WXDFB__) && wxUSE_MSGDLG
|
#if wxUSE_RICHMSGDLG || \
|
||||||
|
(wxUSE_MSGDLG && !defined(__WXMSW__) && !defined(__WXDFB__))
|
||||||
|
|
||||||
// we can't (safely) show the GUI dialog from another thread, only do it
|
// we can't (safely) show the GUI dialog from another thread, only do it
|
||||||
// for the asserts in the main thread
|
// for the asserts in the main thread
|
||||||
if ( wxIsMainThread() )
|
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
|
wxString msgDlg = wxS("A debugging check in this application ")
|
||||||
const wxString stackTrace = GetAssertStackTrace();
|
wxS("has failed.\n\n") + msg;
|
||||||
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.");
|
|
||||||
|
|
||||||
// "No" button means to continue execution, so it should be the default
|
// "No" button means to continue execution, so it should be the default
|
||||||
// action as leaving the "Yes" button the default one would mean that
|
// action as leaving the "Yes" button the default one would mean that
|
||||||
// accidentally pressing Space or Enter would trap and kill the program.
|
// accidentally pressing Space or Enter would trap and kill the program.
|
||||||
switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"),
|
const int flags = wxYES_NO | wxNO_DEFAULT | wxICON_STOP;
|
||||||
wxYES_NO | wxCANCEL | 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
|
// See the comment about using the same variable in
|
||||||
// DoShowAssertDialog().
|
// DoShowAssertDialog().
|
||||||
wxTrapInAssert = true;
|
wxTrapInAssert = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxCANCEL:
|
case wxID_CANCEL:
|
||||||
// no more asserts
|
// 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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // wxUSE_MSGDLG
|
#endif // wxUSE_RICHMSGDLG || wxUSE_MSGDLG
|
||||||
#endif // wxDEBUG_LEVEL
|
#endif // wxDEBUG_LEVEL
|
||||||
|
|
||||||
return wxAppTraitsBase::ShowAssertDialog(msg);
|
return wxAppTraitsBase::ShowAssertDialog(msg);
|
||||||
|
Reference in New Issue
Block a user