X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/524c47aa3adf2af11a3069fd5da035a604f08f66..b0ae60498d2a1cab6cff09d425d235a0847135e8:/src/osx/cocoa/msgdlg.mm diff --git a/src/osx/cocoa/msgdlg.mm b/src/osx/cocoa/msgdlg.mm index bf82c5c956..40ed938450 100644 --- a/src/osx/cocoa/msgdlg.mm +++ b/src/osx/cocoa/msgdlg.mm @@ -4,7 +4,7 @@ // Author: Stefan Csomor // Modified by: // Created: 04/01/98 -// RCS-ID: $Id: msgdlg.cpp 54129 2008-06-11 19:30:52Z SC $ +// RCS-ID: $Id$ // Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -18,13 +18,33 @@ #include "wx/app.h" #endif +#include "wx/control.h" #include "wx/thread.h" +#include "wx/evtloop.h" +#include "wx/modalhook.h" #include "wx/osx/private.h" IMPLEMENT_CLASS(wxMessageDialog, wxDialog) +namespace +{ + NSAlertStyle GetAlertStyleFromWXStyle( long style ) + { + NSAlertStyle alertType = NSWarningAlertStyle; + if (style & wxICON_EXCLAMATION) + alertType = NSCriticalAlertStyle; + else if (style & wxICON_HAND) + alertType = NSWarningAlertStyle; + else if (style & wxICON_INFORMATION) + alertType = NSInformationalAlertStyle; + else if (style & wxICON_QUESTION) + alertType = NSInformationalAlertStyle; + return alertType; + } +} + wxMessageDialog::wxMessageDialog(wxWindow *parent, const wxString& message, const wxString& caption, @@ -32,59 +52,27 @@ wxMessageDialog::wxMessageDialog(wxWindow *parent, const wxPoint& WXUNUSED(pos)) : wxMessageDialogBase(parent, message, caption, style) { - m_yes = _("Yes"); - m_no = _("No"); - m_ok = _("OK"); - m_cancel = _("Cancel"); -} - -bool wxMessageDialog::SetYesNoLabels(const wxString& yes,const wxString& no) -{ - m_yes = yes; - m_no = no; - return true; -} - -bool wxMessageDialog::SetYesNoCancelLabels(const wxString& yes, const wxString& no, const wxString& cancel) -{ - m_yes = yes; - m_no = no; - m_cancel = cancel; - return true; -} - -bool wxMessageDialog::SetOKLabel(const wxString& ok) -{ - m_ok = ok; - return true; + m_sheetDelegate = [[ModalDialogDelegate alloc] init]; + [(ModalDialogDelegate*)m_sheetDelegate setImplementation: this]; } -bool wxMessageDialog::SetOKCancelLabels(const wxString& ok, const wxString& cancel) +wxMessageDialog::~wxMessageDialog() { - m_ok = ok; - m_cancel = cancel; - return true; + [m_sheetDelegate release]; } int wxMessageDialog::ShowModal() { + WX_HOOK_MODAL_DIALOG(); + + wxCFEventLoopPauseIdleEvents pause; + int resultbutton = wxID_CANCEL; const long style = GetMessageDialogStyle(); wxASSERT_MSG( (style & 0x3F) != wxYES, wxT("this style is not supported on Mac") ); - AlertType alertType = kAlertPlainAlert; - if (style & wxICON_EXCLAMATION) - alertType = kAlertCautionAlert; - else if (style & wxICON_HAND) - alertType = kAlertStopAlert; - else if (style & wxICON_INFORMATION) - alertType = kAlertNoteAlert; - else if (style & wxICON_QUESTION) - alertType = kAlertNoteAlert; - - // work out what to display // if the extended text is empty then we use the caption as the title // and the message as the text (for backwards compatibility) @@ -113,12 +101,14 @@ int wxMessageDialog::ShowModal() wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() ); wxCFStringRef cfText( msgtext, GetFont().GetEncoding() ); - wxCFStringRef cfNoString( m_no.c_str(), GetFont().GetEncoding() ); - wxCFStringRef cfYesString( m_yes.c_str(), GetFont().GetEncoding() ); - wxCFStringRef cfOKString( m_ok.c_str() , GetFont().GetEncoding()) ; - wxCFStringRef cfCancelString( m_cancel.c_str(), GetFont().GetEncoding() ); + wxCFStringRef cfNoString( wxControl::GetLabelText(GetNoLabel()), GetFont().GetEncoding() ); + wxCFStringRef cfYesString( wxControl::GetLabelText(GetYesLabel()), GetFont().GetEncoding() ); + wxCFStringRef cfOKString( wxControl::GetLabelText(GetOKLabel()), GetFont().GetEncoding()) ; + wxCFStringRef cfCancelString( wxControl::GetLabelText(GetCancelLabel()), GetFont().GetEncoding() ); - int buttonId[4] = { 0, 0, 0, wxID_CANCEL /* time-out */ }; + NSAlertStyle alertType = GetAlertStyleFromWXStyle(style); + + int m_buttonId[4] = { 0, 0, 0, wxID_CANCEL /* time-out */ }; if (style & wxYES_NO) { @@ -126,159 +116,193 @@ int wxMessageDialog::ShowModal() { defaultButtonTitle = cfNoString; alternateButtonTitle = cfYesString; - buttonId[0] = wxID_NO; - buttonId[1] = wxID_YES; + m_buttonId[0] = wxID_NO; + m_buttonId[1] = wxID_YES; } else { defaultButtonTitle = cfYesString; alternateButtonTitle = cfNoString; - buttonId[0] = wxID_YES; - buttonId[1] = wxID_NO; + m_buttonId[0] = wxID_YES; + m_buttonId[1] = wxID_NO; } if (style & wxCANCEL) { otherButtonTitle = cfCancelString; - buttonId[2] = wxID_CANCEL; + m_buttonId[2] = wxID_CANCEL; } } else { // the MSW implementation even shows an OK button if it is not specified, we'll do the same - buttonId[0] = wxID_OK; + m_buttonId[0] = wxID_OK; // using null as default title does not work on earlier systems defaultButtonTitle = cfOKString; if (style & wxCANCEL) { alternateButtonTitle = cfCancelString; - buttonId[1] = wxID_CANCEL; + m_buttonId[1] = wxID_CANCEL; } } + wxASSERT_MSG( !(style & wxHELP), "wxHELP not supported in non-GUI thread" ); + CFOptionFlags exitButton; OSStatus err = CFUserNotificationDisplayAlert( 0, alertType, NULL, NULL, NULL, cfTitle, cfText, defaultButtonTitle, alternateButtonTitle, otherButtonTitle, &exitButton ); if (err == noErr) - resultbutton = buttonId[exitButton]; + resultbutton = m_buttonId[exitButton]; } else { - short result; + NSAlert* alert = (NSAlert*)ConstructNSAlert(); - AlertStdCFStringAlertParamRec param; - wxCFStringRef cfNoString( m_no.c_str(), GetFont().GetEncoding() ); - wxCFStringRef cfYesString( m_yes.c_str(), GetFont().GetEncoding() ); - wxCFStringRef cfOKString( m_ok.c_str(), GetFont().GetEncoding() ); - wxCFStringRef cfCancelString( m_cancel.c_str(), GetFont().GetEncoding() ); + int button = -1; + button = [alert runModal]; + [alert release]; + ModalFinishedCallback(alert, button); + } - wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() ); - wxCFStringRef cfText( msgtext, GetFont().GetEncoding() ); + return GetReturnCode(); +} - param.movable = true; - param.flags = 0; - param.version = kStdCFStringAlertVersionOne; +void wxMessageDialog::ShowWindowModal() +{ + NSAlert* alert = (NSAlert*)ConstructNSAlert(); - bool skipDialog = false; + wxNonOwnedWindow* parentWindow = NULL; - if (style & wxYES_NO) + m_modality = wxDIALOG_MODALITY_WINDOW_MODAL; + + if (GetParent()) + parentWindow = dynamic_cast(wxGetTopLevelParent(GetParent())); + + wxASSERT_MSG(parentWindow, "Window modal display requires parent."); + + if (parentWindow) + { + NSWindow* nativeParent = parentWindow->GetWXWindow(); + [alert beginSheetModalForWindow: nativeParent modalDelegate: m_sheetDelegate + didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) + contextInfo: nil]; + } +} + +void wxMessageDialog::ModalFinishedCallback(void* WXUNUSED(panel), int resultCode) +{ + int resultbutton = wxID_CANCEL; + if ( resultCode < NSAlertFirstButtonReturn ) + resultbutton = wxID_CANCEL; + else + { + if ( resultCode - NSAlertFirstButtonReturn < m_buttonCount ) + resultbutton = m_buttonId[ resultCode - NSAlertFirstButtonReturn ]; + else + resultbutton = wxID_CANCEL; + } + SetReturnCode(resultbutton); + + if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL) + SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED ); +} + +void* wxMessageDialog::ConstructNSAlert() +{ + const long style = GetMessageDialogStyle(); + + wxASSERT_MSG( (style & 0x3F) != wxYES, wxT("this style is not supported on Mac") ); + + // work out what to display + // if the extended text is empty then we use the caption as the title + // and the message as the text (for backwards compatibility) + // but if the extended message is not empty then we use the message as the title + // and the extended message as the text because that makes more sense + + wxString msgtitle,msgtext; + if(m_extendedMessage.IsEmpty()) + { + msgtitle = m_caption; + msgtext = m_message; + } + else + { + msgtitle = m_message; + msgtext = m_extendedMessage; + } + + NSAlert* alert = [[NSAlert alloc] init]; + NSAlertStyle alertType = GetAlertStyleFromWXStyle(style); + + wxCFStringRef cfNoString( wxControl::GetLabelText(GetNoLabel()), GetFont().GetEncoding() ); + wxCFStringRef cfYesString( wxControl::GetLabelText(GetYesLabel()), GetFont().GetEncoding() ); + wxCFStringRef cfOKString( wxControl::GetLabelText(GetOKLabel()), GetFont().GetEncoding() ); + wxCFStringRef cfCancelString( wxControl::GetLabelText(GetCancelLabel()), GetFont().GetEncoding() ); + + wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() ); + wxCFStringRef cfText( msgtext, GetFont().GetEncoding() ); + + [alert setMessageText:cfTitle.AsNSString()]; + [alert setInformativeText:cfText.AsNSString()]; + [alert setAlertStyle:alertType]; + + m_buttonCount = 0; + + if (style & wxYES_NO) + { + if ( style & wxNO_DEFAULT ) { - if (style & wxCANCEL) - { - param.defaultText = cfYesString; - param.cancelText = cfCancelString; - param.otherText = cfNoString; - param.helpButton = false; - param.defaultButton = style & wxNO_DEFAULT ? kAlertStdAlertOtherButton : kAlertStdAlertOKButton; - param.cancelButton = kAlertStdAlertCancelButton; - } - else - { - param.defaultText = cfYesString; - param.cancelText = NULL; - param.otherText = cfNoString; - param.helpButton = false; - param.defaultButton = style & wxNO_DEFAULT ? kAlertStdAlertOtherButton : kAlertStdAlertOKButton; - param.cancelButton = 0; - } + [alert addButtonWithTitle:cfNoString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_NO; + [alert addButtonWithTitle:cfYesString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_YES; } - // the MSW implementation even shows an OK button if it is not specified, we'll do the same else { - if (style & wxCANCEL) - { - // that's a cancel missing - param.defaultText = cfOKString; - param.cancelText = cfCancelString; - param.otherText = NULL; - param.helpButton = false; - param.defaultButton = kAlertStdAlertOKButton; - param.cancelButton = 0; - } - else - { - param.defaultText = cfOKString; - param.cancelText = NULL; - param.otherText = NULL; - param.helpButton = false; - param.defaultButton = kAlertStdAlertOKButton; - param.cancelButton = 0; - } + [alert addButtonWithTitle:cfYesString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_YES; + [alert addButtonWithTitle:cfNoString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_NO; } - param.position = kWindowDefaultPosition; - if ( !skipDialog ) + if (style & wxCANCEL) { - DialogRef alertRef; - CreateStandardAlert( alertType, cfTitle, cfText, ¶m, &alertRef ); - RunStandardAlert( alertRef, NULL, &result ); + [alert addButtonWithTitle:cfCancelString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_CANCEL; } - else + } + // the MSW implementation even shows an OK button if it is not specified, we'll do the same + else + { + if ( style & wxCANCEL_DEFAULT ) { - return wxID_CANCEL; - } + [alert addButtonWithTitle:cfCancelString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_CANCEL; - if (style & wxOK) + [alert addButtonWithTitle:cfOKString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_OK; + } + else { - switch ( result ) + [alert addButtonWithTitle:cfOKString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_OK; + if (style & wxCANCEL) { - case 1: - resultbutton = wxID_OK; - break; - - case 2: - // TODO: add Cancel button - // if (style & wxCANCEL) - // resultbutton = wxID_CANCEL; - break; - - case 3: - default: - break; + [alert addButtonWithTitle:cfCancelString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_CANCEL; } } - else if (style & wxYES_NO) - { - switch ( result ) - { - case 1: - resultbutton = wxID_YES; - break; - - case 2: - if (!(style & wxCANCEL)) - resultbutton = wxID_CANCEL; - break; - case 3: - resultbutton = wxID_NO; - break; + } - default: - break; - } - } + if ( style & wxHELP ) + { + wxCFStringRef cfHelpString( GetHelpLabel(), GetFont().GetEncoding() ); + [alert addButtonWithTitle:cfHelpString.AsNSString()]; + m_buttonId[ m_buttonCount++ ] = wxID_HELP; } - return resultbutton; + wxASSERT_MSG( m_buttonCount <= WXSIZEOF(m_buttonId), "Too many buttons" ); + + return alert; }