]> git.saurik.com Git - wxWidgets.git/commitdiff
Add support for wxHELP button to wxMessageDialog.
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 4 Aug 2011 22:53:42 +0000 (22:53 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 4 Aug 2011 22:53:42 +0000 (22:53 +0000)
Implement support for wxHELP for wxMSW, wxGTK and wxOSX/Cocoa (at least when
showing the message box from the main thread, there doesn't seem to be any way
to show more than three buttons with CFUserNotificationDisplayAlert() so
"Help" button is not supported when using it).

This is useful not only on its own, i.e. to allow the user to ask for help,
but also because it brings the total number of buttons supported by the
message dialog to 4, meaning that more choices can be offered to the user
(which is rarely, but not quite never, useful).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@68537 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

14 files changed:
docs/changes.txt
include/wx/generic/msgdlgg.h
include/wx/gtk/msgdlg.h
include/wx/msgdlg.h
include/wx/msw/private/msgdlg.h
include/wx/osx/msgdlg.h
interface/wx/msgdlg.h
samples/dialogs/dialogs.cpp
samples/dialogs/dialogs.h
src/common/utilscmn.cpp
src/generic/msgdlgg.cpp
src/gtk/msgdlg.cpp
src/msw/msgdlg.cpp
src/osx/cocoa/msgdlg.mm

index 4023793277f4cf7a29e5cec0f2fb75112a5194c2..7e7620bf750c849985dc797c806d0a9a14b251a2 100644 (file)
@@ -446,6 +446,7 @@ All (GUI):
 
 - Added documented, public wxNavigationEnabled<> class.
 - Added wxTextCtrl::PositionToCoords() (Navaneeth).
+- Added support for wxHELP button to wxMessageDialog.
 - Support float, double and file name values in wxGenericValidator (troelsk).
 - Fix keyboard navigation in wxGrid with hidden columns (ivan_14_32).
 - Add wxDataViewEvent::IsEditCancelled() (Allonii).
index f6583bd3511e7d676381226a732b8e0308e5215b..21db4aa32b672c0c78dcbb13da12e1d67d95ae88 100644 (file)
@@ -32,6 +32,7 @@ protected:
 
     void OnYes(wxCommandEvent& event);
     void OnNo(wxCommandEvent& event);
+    void OnHelp(wxCommandEvent& event);
     void OnCancel(wxCommandEvent& event);
 
     // can be overridden to provide more contents to the dialog
index daab4caac938e91b60648b45c88cb86a9a6d1b1b..8c0a7b095c7dfb49e8b40fcd4b1a32456889184b 100644 (file)
@@ -40,6 +40,7 @@ private:
     virtual wxString GetDefaultNoLabel() const;
     virtual wxString GetDefaultOKLabel() const;
     virtual wxString GetDefaultCancelLabel() const;
+    virtual wxString GetDefaultHelpLabel() const;
 
     // create the real GTK+ dialog: this is done from ShowModal() to allow
     // changing the message between constructing the dialog and showing it
index ca96fc7ff947ad0a2cfbb4b015b05cd0e486cc04..c3e8d9af4fe396d94baae0bbd8e279e05668bab1 100644 (file)
@@ -177,10 +177,16 @@ public:
         return true;
     }
 
+    virtual bool SetHelpLabel(const ButtonLabel& help)
+    {
+        DoSetCustomLabel(m_help, help);
+        return true;
+    }
+
     // test if any custom labels were set
     bool HasCustomLabels() const
     {
-        return !(m_ok.empty() && m_cancel.empty() &&
+        return !(m_ok.empty() && m_cancel.empty() && m_help.empty() &&
                  m_yes.empty() && m_no.empty());
     }
 
@@ -195,6 +201,8 @@ public:
         { return m_ok.empty() ? GetDefaultOKLabel() : m_ok; }
     wxString GetCancelLabel() const
         { return m_cancel.empty() ? GetDefaultCancelLabel() : m_cancel; }
+    wxString GetHelpLabel() const
+        { return m_help.empty() ? GetDefaultHelpLabel() : m_help; }
 
     // based on message dialog style, returns exactly one of: wxICON_NONE,
     // wxICON_ERROR, wxICON_WARNING, wxICON_QUESTION, wxICON_INFORMATION
@@ -250,6 +258,7 @@ protected:
     const wxString& GetCustomYesLabel() const { return m_yes; }
     const wxString& GetCustomNoLabel() const { return m_no; }
     const wxString& GetCustomOKLabel() const { return m_ok; }
+    const wxString& GetCustomHelpLabel() const { return m_help; }
     const wxString& GetCustomCancelLabel() const { return m_cancel; }
 
 private:
@@ -259,13 +268,15 @@ private:
     virtual wxString GetDefaultNoLabel() const { return wxGetTranslation("No"); }
     virtual wxString GetDefaultOKLabel() const { return wxGetTranslation("OK"); }
     virtual wxString GetDefaultCancelLabel() const { return wxGetTranslation("Cancel"); }
+    virtual wxString GetDefaultHelpLabel() const { return wxGetTranslation("Help"); }
 
     // labels for the buttons, initially empty meaning that the defaults should
     // be used, use GetYes/No/OK/CancelLabel() to access them
     wxString m_yes,
              m_no,
              m_ok,
-             m_cancel;
+             m_cancel,
+             m_help;
 
     wxDECLARE_NO_COPY_CLASS(wxMessageDialogBase);
 };
index 5df01fc10d4b5173b04ec7068361b841e67026e9..45db8702e73e8132654e463cb14dc6ed717948db 100644 (file)
@@ -30,8 +30,10 @@ namespace wxMSWMessageDialog
     class wxMSWTaskDialogConfig
     {
     public:
+        enum { MAX_BUTTONS = 4  };
+
         wxMSWTaskDialogConfig()
-            : buttons(new TASKDIALOG_BUTTON[3]),
+            : buttons(new TASKDIALOG_BUTTON[MAX_BUTTONS]),
               parent(NULL),
               iconId(0),
               style(0),
@@ -53,6 +55,7 @@ namespace wxMSWMessageDialog
         wxString btnNoLabel;
         wxString btnOKLabel;
         wxString btnCancelLabel;
+        wxString btnHelpLabel;
 
         // Will create a task dialog with it's paremeters for it's creation
         // stored in the provided TASKDIALOGCONFIG parameter.
index cad3de35b7a6f72b841437aaba175c5f76755d00..9c3d38067dca082a9f6f61926f7aa0643b84f45c 100644 (file)
@@ -43,7 +43,7 @@ protected:
     void* ConstructNSAlert();
 #endif
 
-    int m_buttonId[3];
+    int m_buttonId[4];
     int m_buttonCount;
 
 #if wxOSX_USE_COCOA
index 0448b043660af26faf517574552bf51f76620a09..70aba8cca16d42174d41d47551d6ffc49560d907 100644 (file)
         Puts Yes and No buttons in the message box. It is recommended to always
         use @c wxCANCEL with this style as otherwise the message box won't have
         a close button under wxMSW and the user will be forced to answer it.
+    @style{wxHELP}
+        Puts a Help button to the message box. This button can have special
+        appearance or be specially positioned if its label is not changed from
+        the default one. Notice that using this button is not supported when
+        showing a message box from non-main thread in wxOSX/Cocoa and it is not
+        supported in wxOSX/Carbon at all. @since 2.9.3.
     @style{wxNO_DEFAULT}
         Makes the "No" button default, can only be used with @c wxYES_NO.
     @style{wxCANCEL_DEFAULT}
@@ -116,6 +122,19 @@ public:
     */
     virtual void SetExtendedMessage(const wxString& extendedMessage);
 
+    /**
+        Sets the label for the Help button.
+
+        Please see the remarks in SetYesNoLabels() documentation.
+
+        Notice that changing the label of the help button resets its special
+        status (if any, this depends on the platform) and it will be treated
+        just like another button in this case.
+
+        @since 2.9.3
+     */
+    virtual bool SetHelpLabel(const ButtonLabel& help);
+
     /**
         Sets the message shown by the dialog.
 
@@ -190,7 +209,8 @@ public:
     virtual bool SetYesNoLabels(const ButtonLabel& yes, const ButtonLabel& no);
 
     /**
-        Shows the dialog, returning one of wxID_OK, wxID_CANCEL, wxID_YES, wxID_NO.
+        Shows the dialog, returning one of wxID_OK, wxID_CANCEL, wxID_YES,
+        wxID_NO or wxID_HELP.
 
         Notice that this method returns the identifier of the button which was
         clicked unlike wxMessageBox() function.
@@ -215,9 +235,9 @@ public:
     extended text and custom labels for the message box buttons, are not
     provided by this function but only by wxMessageDialog.
 
-    The return value is one of: @c wxYES, @c wxNO, @c wxCANCEL or @c wxOK
-    (notice that this return value is @b different from the return value of
-    wxMessageDialog::ShowModal()).
+    The return value is one of: @c wxYES, @c wxNO, @c wxCANCEL, @c wxOK or @c
+    wxHELP (notice that this return value is @b different from the return value
+    of wxMessageDialog::ShowModal()).
 
     For example:
     @code
index 335cc16ca2151b83340cdcac554f3cc6b237c410..14f1a8031898e6d1b93a337b095488c73e5898b6 100644 (file)
@@ -2669,6 +2669,7 @@ const TestMessageBoxDialog::BtnInfo TestMessageBoxDialog::ms_btnInfo[] =
     { wxNO,     "&No"     },
     { wxOK,     "&Ok"     },
     { wxCANCEL, "&Cancel" },
+    { wxHELP,   "&Help"   },
 };
 
 BEGIN_EVENT_TABLE(TestMessageBoxDialog, wxDialog)
@@ -2889,6 +2890,11 @@ void TestMessageBoxDialog::PrepareMessageDialog(wxMessageDialogBase &dlg)
             dlg.SetOKLabel(m_labels[Btn_Ok]->GetValue());
         }
     }
+
+    if ( style & wxHELP )
+    {
+        dlg.SetHelpLabel(m_labels[Btn_Help]->GetValue());
+    }
 }
 
 void TestMessageBoxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
@@ -2896,7 +2902,34 @@ void TestMessageBoxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
     wxMessageDialog dlg(this, GetMessage(), "Test Message Box", GetStyle());
     PrepareMessageDialog(dlg);
 
-    dlg.ShowModal();
+    wxString btnName;
+    switch ( dlg.ShowModal() )
+    {
+        case wxID_OK:
+            btnName = "OK";
+            break;
+
+        case wxID_CANCEL:
+            // Avoid the extra message box if the dialog was cancelled.
+            return;
+
+        case wxID_YES:
+            btnName = "Yes";
+            break;
+
+        case wxID_NO:
+            btnName = "No";
+            break;
+
+        case wxID_HELP:
+            btnName = "Help";
+            break;
+
+        default:
+            btnName = "Unknown";
+    }
+
+    wxLogMessage("Dialog was closed with the \"%s\" button.", btnName);
 }
 
 void TestMessageBoxDialog::OnClose(wxCommandEvent& WXUNUSED(event))
index fbad49919a3137d8ce9e32fa31e7527711e69f50..61dd0f85aa3c4db6b940606c9a4ce8c81dbd6d76 100644 (file)
@@ -228,6 +228,7 @@ private:
         Btn_No,
         Btn_Ok,
         Btn_Cancel,
+        Btn_Help,
         Btn_Max
     };
 
index 6e9a224e9d5a0e74c3b25976a35a091449ea8e81..4ff8dade7aa3abccdb4cc61407bc825d01e0b6d1 100644 (file)
@@ -1361,6 +1361,8 @@ int wxMessageBox(const wxString& message, const wxString& caption, long style,
             return wxNO;
         case wxID_CANCEL:
             return wxCANCEL;
+        case wxID_HELP:
+            return wxHELP;
     }
 
     wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
index 3fd78a7269414bd5664419926e562b77ca98fdd0..c3dd7a8067f28e0ec8b74adbc634c28870bc3af1 100644 (file)
@@ -74,6 +74,7 @@ protected:
 BEGIN_EVENT_TABLE(wxGenericMessageDialog, wxDialog)
         EVT_BUTTON(wxID_YES, wxGenericMessageDialog::OnYes)
         EVT_BUTTON(wxID_NO, wxGenericMessageDialog::OnNo)
+        EVT_BUTTON(wxID_HELP, wxGenericMessageDialog::OnHelp)
         EVT_BUTTON(wxID_CANCEL, wxGenericMessageDialog::OnCancel)
 END_EVENT_TABLE()
 
@@ -133,6 +134,13 @@ wxSizer *wxGenericMessageDialog::CreateMsgDlgButtonSizer()
                 btnDef = yes;
         }
 
+        if ( m_dialogStyle & wxHELP )
+        {
+            wxButton * const
+                help = new wxButton(this, wxID_HELP, GetCustomHelpLabel());
+            sizerStd->AddButton(help);
+        }
+
         if ( btnDef )
         {
             btnDef->SetDefault();
@@ -148,7 +156,7 @@ wxSizer *wxGenericMessageDialog::CreateMsgDlgButtonSizer()
     // Use standard labels for all buttons
     return CreateSeparatedButtonSizer
            (
-                m_dialogStyle & (wxOK | wxCANCEL | wxYES_NO |
+                m_dialogStyle & (wxOK | wxCANCEL | wxHELP | wxYES_NO |
                                  wxNO_DEFAULT | wxCANCEL_DEFAULT)
            );
 }
@@ -242,6 +250,11 @@ void wxGenericMessageDialog::OnNo(wxCommandEvent& WXUNUSED(event))
     EndModal( wxID_NO );
 }
 
+void wxGenericMessageDialog::OnHelp(wxCommandEvent& WXUNUSED(event))
+{
+    EndModal( wxID_HELP );
+}
+
 void wxGenericMessageDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
 {
     // Allow cancellation via ESC/Close button except if
index d459602f0b015e45e808ed465740d46808024ad6..2b47ac27ef63382bd35e6802fb1b9b77b6f343fc 100644 (file)
@@ -74,6 +74,11 @@ wxString wxMessageDialog::GetDefaultCancelLabel() const
     return GTK_STOCK_CANCEL;
 }
 
+wxString wxMessageDialog::GetDefaultHelpLabel() const
+{
+    return GTK_STOCK_HELP;
+}
+
 void wxMessageDialog::DoSetCustomLabel(wxString& var, const ButtonLabel& label)
 {
     int stockId = label.GetStockId();
@@ -135,16 +140,21 @@ void wxMessageDialog::GTKCreateMsgDialog()
     // when using custom labels, we have to add all the buttons ourselves
     if ( !HasCustomLabels() )
     {
-        if ( m_dialogStyle & wxYES_NO )
+        // "Help" button is not supported by predefined combinations so we
+        // always need to create the buttons manually when it's used.
+        if ( !(m_dialogStyle & wxHELP) )
         {
-            if ( !(m_dialogStyle & wxCANCEL) )
-                buttons = GTK_BUTTONS_YES_NO;
-            //else: no standard GTK_BUTTONS_YES_NO_CANCEL so leave as NONE
-        }
-        else if ( m_dialogStyle & wxOK )
-        {
-            buttons = m_dialogStyle & wxCANCEL ? GTK_BUTTONS_OK_CANCEL
-                                               : GTK_BUTTONS_OK;
+            if ( m_dialogStyle & wxYES_NO )
+            {
+                if ( !(m_dialogStyle & wxCANCEL) )
+                    buttons = GTK_BUTTONS_YES_NO;
+                //else: no standard GTK_BUTTONS_YES_NO_CANCEL so leave as NONE
+            }
+            else if ( m_dialogStyle & wxOK )
+            {
+                buttons = m_dialogStyle & wxCANCEL ? GTK_BUTTONS_OK_CANCEL
+                                                   : GTK_BUTTONS_OK;
+            }
         }
     }
 
@@ -211,9 +221,16 @@ void wxMessageDialog::GTKCreateMsgDialog()
     const bool addButtons = buttons == GTK_BUTTONS_NONE;
 #endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
 
-    if ( m_dialogStyle & wxYES_NO ) // Yes/No or Yes/No/Cancel dialog
+
+    if ( addButtons )
     {
-        if ( addButtons )
+        if ( m_dialogStyle & wxHELP )
+        {
+            gtk_dialog_add_button(dlg, wxGTK_CONV(GetHelpLabel()),
+                                  GTK_RESPONSE_HELP);
+        }
+
+        if ( m_dialogStyle & wxYES_NO ) // Yes/No or Yes/No/Cancel dialog
         {
             // Add the buttons in the correct order which is, according to
             // http://library.gnome.org/devel/hig-book/stable/windows-alert.html.en
@@ -233,32 +250,29 @@ void wxMessageDialog::GTKCreateMsgDialog()
             gtk_dialog_add_button(dlg, wxGTK_CONV(GetYesLabel()),
                                   GTK_RESPONSE_YES);
         }
-
-        // it'd probably be harmless to call gtk_dialog_set_default_response()
-        // twice but why do it if we're going to change the default below
-        // anyhow
-        if ( !(m_dialogStyle & wxCANCEL_DEFAULT) )
-        {
-            gtk_dialog_set_default_response(dlg,
-                                            m_dialogStyle & wxNO_DEFAULT
-                                                ? GTK_RESPONSE_NO
-                                                : GTK_RESPONSE_YES);
-        }
-    }
-    else if ( addButtons ) // Ok or Ok/Cancel dialog
-    {
-        gtk_dialog_add_button(dlg, wxGTK_CONV(GetOKLabel()), GTK_RESPONSE_OK);
-        if ( m_dialogStyle & wxCANCEL )
+        else // Ok or Ok/Cancel dialog
         {
-            gtk_dialog_add_button(dlg, wxGTK_CONV(GetCancelLabel()),
-                                  GTK_RESPONSE_CANCEL);
+            gtk_dialog_add_button(dlg, wxGTK_CONV(GetOKLabel()), GTK_RESPONSE_OK);
+            if ( m_dialogStyle & wxCANCEL )
+            {
+                gtk_dialog_add_button(dlg, wxGTK_CONV(GetCancelLabel()),
+                                      GTK_RESPONSE_CANCEL);
+            }
         }
     }
 
+    gint defaultButton;
     if ( m_dialogStyle & wxCANCEL_DEFAULT )
-    {
-        gtk_dialog_set_default_response(dlg, GTK_RESPONSE_CANCEL);
-    }
+        defaultButton = GTK_RESPONSE_CANCEL;
+    else if ( m_dialogStyle & wxNO_DEFAULT )
+        defaultButton = GTK_RESPONSE_NO;
+    else if ( m_dialogStyle & wxYES_NO )
+        defaultButton = GTK_RESPONSE_YES;
+    else // No need to change the default value, whatever it is.
+        defaultButton = GTK_RESPONSE_NONE;
+
+    if ( defaultButton != GTK_RESPONSE_NONE )
+        gtk_dialog_set_default_response(dlg, defaultButton);
 }
 
 int wxMessageDialog::ShowModal()
@@ -302,6 +316,8 @@ int wxMessageDialog::ShowModal()
             return wxID_YES;
         case GTK_RESPONSE_NO:
             return wxID_NO;
+        case GTK_RESPONSE_HELP:
+            return wxID_HELP;
     }
 }
 
index 7c786e51416f78d44d6db7dda540af3c4b8db35e..b0118ae2430f6cd2e55cf823dad1bb0829ffd114 100644 (file)
@@ -511,6 +511,11 @@ int wxMessageDialog::ShowMessageBox()
         }
     }
 
+    if ( wxStyle & wxHELP )
+    {
+        msStyle |= MB_HELP;
+    }
+
     // set the icon style
     switch ( GetEffectiveIcon() )
     {
@@ -630,7 +635,7 @@ void wxMessageDialog::DoCentre(int dir)
 #ifdef wxHAS_MSW_TASKDIALOG
 
 wxMSWTaskDialogConfig::wxMSWTaskDialogConfig(const wxMessageDialogBase& dlg)
-                     : buttons(new TASKDIALOG_BUTTON[3])
+                     : buttons(new TASKDIALOG_BUTTON[MAX_BUTTONS])
 {
     parent = dlg.GetParentForModalDialog();
     caption = dlg.GetCaption();
@@ -665,6 +670,7 @@ wxMSWTaskDialogConfig::wxMSWTaskDialogConfig(const wxMessageDialogBase& dlg)
     btnNoLabel = dlg.GetNoLabel();
     btnOKLabel = dlg.GetOKLabel();
     btnCancelLabel = dlg.GetCancelLabel();
+    btnHelpLabel = dlg.GetHelpLabel();
 }
 
 void wxMSWTaskDialogConfig::MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc)
@@ -755,6 +761,15 @@ void wxMSWTaskDialogConfig::MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc)
             AddTaskDialogButton(tdc, IDCANCEL, TDCBF_CANCEL_BUTTON, btnOKLabel);
         }
     }
+
+    if ( style & wxHELP )
+    {
+        // There is no support for "Help" button in the task dialog, it can
+        // only show "Retry" or "Close" ones.
+        useCustomLabels = true;
+
+        AddTaskDialogButton(tdc, IDHELP, 0 /* not used */, btnHelpLabel);
+    }
 }
 
 void wxMSWTaskDialogConfig::AddTaskDialogButton(TASKDIALOGCONFIG &tdc,
@@ -770,6 +785,10 @@ void wxMSWTaskDialogConfig::AddTaskDialogButton(TASKDIALOGCONFIG &tdc,
         tdBtn.nButtonID = btnCustomId;
         tdBtn.pszButtonText = customLabel.wx_str();
         tdc.cButtons++;
+
+        // We should never have more than 4 buttons currently as this is the
+        // maximal number of buttons supported by the message dialog.
+        wxASSERT_MSG( tdc.cButtons <= MAX_BUTTONS, wxT("Too many buttons") );
     }
     else
     {
@@ -839,6 +858,9 @@ int wxMSWMessageDialog::MSWTranslateReturnCode(int msAns)
         case IDNO:
             ans = wxID_NO;
             break;
+        case IDHELP:
+            ans = wxID_HELP;
+            break;
     }
 
     return ans;
index ad44f5560058760d57947ba283a4ebfadc735d99..445a097caa5f1c9887a708fff6ff472fd78baa83 100644 (file)
@@ -138,6 +138,8 @@ int wxMessageDialog::ShowModal()
             }
         }
 
+        wxASSERT_MSG( !(style & wxHELP), "wxHELP not supported in non-GUI thread" );
+
         CFOptionFlags exitButton;
         OSStatus err = CFUserNotificationDisplayAlert(
             0, alertType, NULL, NULL, NULL, cfTitle, cfText,
@@ -285,5 +287,15 @@ void* wxMessageDialog::ConstructNSAlert()
         }
 
     }
+
+    if ( style & wxHELP )
+    {
+        wxCFStringRef cfHelpString( GetHelpLabel(), GetFont().GetEncoding() );
+        [alert addButtonWithTitle:cfHelpString.AsNSString()];
+        m_buttonId[ m_buttonCount++ ] = wxID_HELP;
+    }
+
+    wxASSERT_MSG( m_buttonCount <= WXSIZEOF(m_buttonId), "Too many buttons" );
+
     return alert;
 }