Get ShowWindowModal behavior working under OS X Cocoa for file, dir and message dialogs.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63291 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Kevin Ollivier
2010-01-28 04:06:23 +00:00
parent 896576e31e
commit bfa92264c0
10 changed files with 312 additions and 182 deletions

View File

@@ -55,6 +55,8 @@ WXDLLIMPEXP_BASE wxString wxMacFSRefToPath( const FSRef *fsRef , CFStringRef add
WXDLLIMPEXP_BASE OSStatus wxMacPathToFSRef( const wxString&path , FSRef *fsRef );
WXDLLIMPEXP_BASE wxString wxMacHFSUniStrToString( ConstHFSUniStr255Param uniname );
class WXDLLIMPEXP_FWD_CORE wxDialog;
//
//
//
@@ -346,8 +348,10 @@ protected :
{
BOOL sheetFinished;
int resultCode;
wxDialog* impl;
}
- (void)setImplementation: (wxDialog *)dialog;
- (BOOL)finished;
- (int)code;
- (void)waitForSheetToFinish;

View File

@@ -66,6 +66,10 @@ public:
wxDialogModality GetModality() const;
#if wxOSX_USE_COCOA
virtual void ModalFinishedCallback(void* WXUNUSED(panel), int WXUNUSED(returnCode)) {}
#endif
protected:
// show modal dialog and enter modal loop
void DoShowModal();
@@ -79,10 +83,10 @@ protected:
// needed for cleanup on the Cocoa side.
void EndWindowModal();
wxDialogModality m_modality;
private:
void Init();
wxDialogModality m_modality;
};
#endif

View File

@@ -25,6 +25,11 @@ public:
virtual int ShowModal();
#if wxOSX_USE_COCOA
virtual void ShowWindowModal();
virtual void ModalFinishedCallback(void* panel, int returnCode);
#endif
protected:
DECLARE_DYNAMIC_CLASS(wxDirDialog)

View File

@@ -39,6 +39,11 @@ public:
virtual int ShowModal();
#if wxOSX_USE_COCOA
virtual void ShowWindowModal();
virtual void ModalFinishedCallback(void* panel, int resultCode);
#endif
protected:
// not supported for file dialog, RR
virtual void DoSetSize(int WXUNUSED(x), int WXUNUSED(y),

View File

@@ -24,12 +24,24 @@ public:
virtual int ShowModal();
#if wxOSX_USE_COCOA
virtual void ShowWindowModal();
virtual void ModalFinishedCallback(void* panel, int resultCode);
#endif
protected:
// not supported for message dialog
virtual void DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
int WXUNUSED(width), int WXUNUSED(height),
int WXUNUSED(sizeFlags) = wxSIZE_AUTO) {}
#if wxOSX_USE_COCOA
void* ConstructNSAlert();
#endif
int m_buttonId[3];
int m_buttonCount;
DECLARE_DYNAMIC_CLASS(wxMessageDialog)
};

View File

@@ -47,11 +47,44 @@ wxDirDialog::wxDirDialog(wxWindow *parent, const wxString& message,
SetPath(defaultPath);
}
void wxDirDialog::ShowWindowModal()
{
wxCFStringRef dir( m_path );
m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
[oPanel setCanChooseDirectories:YES];
[oPanel setResolvesAliases:YES];
[oPanel setCanChooseFiles:NO];
wxCFStringRef cf( m_message );
[oPanel setMessage:cf.AsNSString()];
if ( HasFlag(wxDD_NEW_DIR_BUTTON) )
[oPanel setCanCreateDirectories:YES];
wxNonOwnedWindow* parentWindow = NULL;
if (GetParent())
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
wxASSERT_MSG(parentWindow, "Window modal display requires parent.");
if (parentWindow)
{
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[sheetDelegate setImplementation: this];
[oPanel beginSheetForDirectory:dir.AsNSString() file:nil types: nil
modalForWindow: nativeParent modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
}
}
int wxDirDialog::ShowModal()
{
int result = wxID_CANCEL;
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
[oPanel setCanChooseDirectories:YES];
[oPanel setResolvesAliases:YES];
@@ -67,42 +100,28 @@ int wxDirDialog::ShowModal()
m_path = wxEmptyString;
wxNonOwnedWindow* parentWindow = NULL;
int returnCode = -1;
if (GetParent())
{
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
}
else
{
fprintf(stderr, "No parent!\n");
}
returnCode = (NSInteger)[oPanel runModalForDirectory:dir.AsNSString() file:nil types:nil];
ModalFinishedCallback(oPanel, returnCode);
return GetReturnCode();
}
void wxDirDialog::ModalFinishedCallback(void* panel, int returnCode)
{
int result = wxID_CANCEL;
/*
if (parentWindow)
{
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[oPanel beginSheetForDirectory:dir.AsNSString() file:nil types: nil
modalForWindow: nativeParent modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
[sheetDelegate waitForSheetToFinish];
returnCode = [sheetDelegate code];
[sheetDelegate release];
}
else
*/
{
returnCode = (NSInteger)[oPanel runModalForDirectory:dir.AsNSString() file:nil types:nil];
}
if (returnCode == NSOKButton )
{
NSOpenPanel* oPanel = (NSOpenPanel*)panel;
SetPath( wxCFStringRef::AsString([[oPanel filenames] objectAtIndex:0]));
result = wxID_OK;
}
return result;
SetReturnCode(result);
if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL)
SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED );
}
#endif // wxUSE_DIRDLG

View File

@@ -140,10 +140,63 @@ NSArray* GetTypesFromFilter( const wxString filter )
return types;
}
void wxFileDialog::ShowWindowModal()
{
wxCFStringRef cf( m_message );
wxCFStringRef dir( m_dir );
wxCFStringRef file( m_fileName );
wxNonOwnedWindow* parentWindow = NULL;
m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
if (GetParent())
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
wxASSERT_MSG(parentWindow, "Window modal display requires parent.");
if (HasFlag(wxFD_SAVE))
{
NSSavePanel* sPanel = [NSSavePanel savePanel];
// makes things more convenient:
[sPanel setCanCreateDirectories:YES];
[sPanel setMessage:cf.AsNSString()];
// if we should be able to descend into pacakges we must somehow
// be able to pass this in
[sPanel setTreatsFilePackagesAsDirectories:NO];
[sPanel setCanSelectHiddenExtension:YES];
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[sheetDelegate setImplementation: this];
[sPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
modalForWindow: nativeParent modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
}
else
{
NSArray* types = GetTypesFromFilter( m_wildCard ) ;
NSOpenPanel* oPanel = [NSOpenPanel openPanel];
[oPanel setTreatsFilePackagesAsDirectories:NO];
[oPanel setCanChooseDirectories:NO];
[oPanel setResolvesAliases:YES];
[oPanel setCanChooseFiles:YES];
[oPanel setMessage:cf.AsNSString()];
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[sheetDelegate setImplementation: this];
[oPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
types: types modalForWindow: nativeParent
modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
}
}
int wxFileDialog::ShowModal()
{
int result = wxID_CANCEL;
NSSavePanel *panel = nil;
wxCFStringRef cf( m_message );
@@ -180,34 +233,8 @@ int wxFileDialog::ShowModal()
{
}
/*
if (parentWindow)
{
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[sPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
modalForWindow: nativeParent modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
[sheetDelegate waitForSheetToFinish];
returnCode = [sheetDelegate code];
[sheetDelegate release];
}
else
*/
{
returnCode = [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ];
}
if (returnCode == NSOKButton )
{
panel = sPanel;
result = wxID_OK;
m_path = wxCFStringRef::AsString([sPanel filename]);
m_fileName = wxFileNameFromPath(m_path);
m_dir = wxPathOnly( m_path );
}
returnCode = [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ];
ModalFinishedCallback(sPanel, returnCode);
}
else
{
@@ -219,26 +246,36 @@ int wxFileDialog::ShowModal()
[oPanel setCanChooseFiles:YES];
[oPanel setMessage:cf.AsNSString()];
/*
if (parentWindow)
{
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[oPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString()
types: types modalForWindow: nativeParent
modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
[sheetDelegate waitForSheetToFinish];
returnCode = [sheetDelegate code];
[sheetDelegate release];
}
else
*/
{
returnCode = [oPanel runModalForDirectory:dir.AsNSString()
returnCode = [oPanel runModalForDirectory:dir.AsNSString()
file:file.AsNSString() types:types];
ModalFinishedCallback(oPanel, returnCode);
if ( types != nil )
[types release];
}
return GetReturnCode();
}
void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode)
{
int result = wxID_CANCEL;
if (HasFlag(wxFD_SAVE))
{
if (returnCode == NSOKButton )
{
NSSavePanel* sPanel = (NSSavePanel*)panel;
result = wxID_OK;
m_path = wxCFStringRef::AsString([sPanel filename]);
m_fileName = wxFileNameFromPath(m_path);
m_dir = wxPathOnly( m_path );
}
}
else
{
NSOpenPanel* oPanel = (NSOpenPanel*)panel;
if (returnCode == NSOKButton )
{
panel = oPanel;
@@ -257,11 +294,11 @@ int wxFileDialog::ShowModal()
}
}
}
if ( types != nil )
[types release];
}
SetReturnCode(result);
return result;
if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL)
SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED );
}
#endif // wxUSE_FILEDLG

View File

@@ -86,7 +86,7 @@ int wxMessageDialog::ShowModal()
wxCFStringRef cfOKString( GetOKLabel(), GetFont().GetEncoding()) ;
wxCFStringRef cfCancelString( GetCancelLabel(), GetFont().GetEncoding() );
int buttonId[4] = { 0, 0, 0, wxID_CANCEL /* time-out */ };
int m_buttonId[4] = { 0, 0, 0, wxID_CANCEL /* time-out */ };
if (style & wxYES_NO)
{
@@ -94,32 +94,32 @@ 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;
}
}
@@ -128,99 +128,135 @@ int wxMessageDialog::ShowModal()
0, alertType, NULL, NULL, NULL, cfTitle, cfText,
defaultButtonTitle, alternateButtonTitle, otherButtonTitle, &exitButton );
if (err == noErr)
resultbutton = buttonId[exitButton];
resultbutton = m_buttonId[exitButton];
}
else
{
NSAlert* alert = [[NSAlert alloc] init];
NSAlert* alert = (NSAlert*)ConstructNSAlert();
wxCFStringRef cfNoString( GetNoLabel(), GetFont().GetEncoding() );
wxCFStringRef cfYesString( GetYesLabel(), GetFont().GetEncoding() );
wxCFStringRef cfOKString( GetOKLabel(), GetFont().GetEncoding() );
wxCFStringRef cfCancelString( GetCancelLabel(), GetFont().GetEncoding() );
wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() );
wxCFStringRef cfText( msgtext, GetFont().GetEncoding() );
[alert setMessageText:cfTitle.AsNSString()];
[alert setInformativeText:cfText.AsNSString()];
int buttonId[3] = { 0, 0, 0 };
int buttonCount = 0;
if (style & wxYES_NO)
{
if ( style & wxNO_DEFAULT )
{
[alert addButtonWithTitle:cfNoString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_NO;
[alert addButtonWithTitle:cfYesString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_YES;
}
else
{
[alert addButtonWithTitle:cfYesString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_YES;
[alert addButtonWithTitle:cfNoString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_NO;
}
if (style & wxCANCEL)
{
[alert addButtonWithTitle:cfCancelString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_CANCEL;
}
}
// the MSW implementation even shows an OK button if it is not specified, we'll do the same
else
{
[alert addButtonWithTitle:cfOKString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_OK;
if (style & wxCANCEL)
{
[alert addButtonWithTitle:cfCancelString.AsNSString()];
buttonId[ buttonCount++ ] = wxID_CANCEL;
}
}
wxNonOwnedWindow* parentWindow = NULL;
int button = -1;
if (GetParent())
{
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
}
/*
if (parentWindow)
{
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[alert beginSheetModalForWindow: nativeParent modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
[sheetDelegate waitForSheetToFinish];
button = [sheetDelegate code];
[sheetDelegate release];
}
else
*/
{
button = [alert runModal];
}
button = [alert runModal];
[alert release];
if ( button < NSAlertFirstButtonReturn )
resultbutton = wxID_CANCEL;
else
{
if ( button - NSAlertFirstButtonReturn < buttonCount )
resultbutton = buttonId[ button - NSAlertFirstButtonReturn ];
else
resultbutton = wxID_CANCEL;
}
ModalFinishedCallback(alert, button);
}
return resultbutton;
return GetReturnCode();
}
void wxMessageDialog::ShowWindowModal()
{
NSAlert* alert = (NSAlert*)ConstructNSAlert();
wxNonOwnedWindow* parentWindow = NULL;
m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
if (GetParent())
parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
wxASSERT_MSG(parentWindow, "Window modal display requires parent.");
if (parentWindow)
{
NSWindow* nativeParent = parentWindow->GetWXWindow();
ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init];
[sheetDelegate setImplementation: this];
[alert beginSheetModalForWindow: nativeParent modalDelegate: sheetDelegate
didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
contextInfo: nil];
}
}
void wxMessageDialog::ModalFinishedCallback(void* 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];
wxCFStringRef cfNoString( GetNoLabel(), GetFont().GetEncoding() );
wxCFStringRef cfYesString( GetYesLabel(), GetFont().GetEncoding() );
wxCFStringRef cfOKString( GetOKLabel(), GetFont().GetEncoding() );
wxCFStringRef cfCancelString( GetCancelLabel(), GetFont().GetEncoding() );
wxCFStringRef cfTitle( msgtitle, GetFont().GetEncoding() );
wxCFStringRef cfText( msgtext, GetFont().GetEncoding() );
[alert setMessageText:cfTitle.AsNSString()];
[alert setInformativeText:cfText.AsNSString()];
m_buttonCount = 0;
if (style & wxYES_NO)
{
if ( style & wxNO_DEFAULT )
{
[alert addButtonWithTitle:cfNoString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_NO;
[alert addButtonWithTitle:cfYesString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_YES;
}
else
{
[alert addButtonWithTitle:cfYesString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_YES;
[alert addButtonWithTitle:cfNoString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_NO;
}
if (style & wxCANCEL)
{
[alert addButtonWithTitle:cfCancelString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_CANCEL;
}
}
// the MSW implementation even shows an OK button if it is not specified, we'll do the same
else
{
[alert addButtonWithTitle:cfOKString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_OK;
if (style & wxCANCEL)
{
[alert addButtonWithTitle:cfCancelString.AsNSString()];
m_buttonId[ m_buttonCount++ ] = wxID_CANCEL;
}
}
return alert;
}

View File

@@ -11,14 +11,13 @@
#include "wx/wxprec.h"
#include "wx/wxprec.h"
#include "wx/utils.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/app.h"
#if wxUSE_GUI
#include "wx/dialog.h"
#include "wx/toplevel.h"
#include "wx/font.h"
#endif
@@ -176,9 +175,15 @@ void wxMacWakeUp()
[super init];
sheetFinished = NO;
resultCode = -1;
impl = 0;
return self;
}
- (void)setImplementation: (wxDialog *)dialog
{
impl = dialog;
}
- (BOOL)finished
{
return sheetFinished;
@@ -205,6 +210,9 @@ void wxMacWakeUp()
// NSAlerts don't need nor respond to orderOut
if ([sheet respondsToSelector:@selector(orderOut:)])
[sheet orderOut: self];
if (impl)
impl->ModalFinishedCallback(sheet, returnCode);
}
@end

View File

@@ -122,7 +122,7 @@ bool wxDialog::Show(bool show)
// Replacement for Show(true) for modal dialogs - returns return code
int wxDialog::ShowModal()
{
m_modality = wxDIALOG_MODALITY_WINDOW_MODAL;
m_modality = wxDIALOG_MODALITY_APP_MODAL;
Show();