X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/13390af486a8b9b72408260f6d89309870a43812..7c60222510bc5e197b12f153c4bf05db66cb0f4a:/src/osx/cocoa/filedlg.mm?ds=inline diff --git a/src/osx/cocoa/filedlg.mm b/src/osx/cocoa/filedlg.mm index 12fe95f056..40d4f4645f 100644 --- a/src/osx/cocoa/filedlg.mm +++ b/src/osx/cocoa/filedlg.mm @@ -4,7 +4,7 @@ // Author: Ryan Norton // Modified by: // Created: 2004-10-02 -// RCS-ID: $Id: filedlg.mm 40007 2006-07-05 13:10:46Z SC $ +// RCS-ID: $Id$ // Copyright: (c) Ryan Norton // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -27,13 +27,20 @@ #ifndef WX_PRECOMP #include "wx/msgdlg.h" #include "wx/app.h" + #include "wx/sizer.h" + #include "wx/stattext.h" + #include "wx/choice.h" #endif #include "wx/filename.h" #include "wx/tokenzr.h" +#include "wx/evtloop.h" #include "wx/osx/private.h" #include "wx/sysopt.h" +#include "wx/modalhook.h" + +#include // ============================================================================ // implementation @@ -46,6 +53,32 @@ // then the delegate method - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename will have to // be implemented +namespace +{ + +bool HasAppKit_10_6() +{ + // Even if we require 10.6, we might be loaded by an application that + // was linked against 10.5. setAllowedFileTypes will still be ignored + // in this case. From NSSavePanel.h: + // NSOpenPanel: On versions less than 10.6, this property is ignored. + // For applications that link against 10.6 and higher, this property will + // determine which files should be enabled in the open panel. + int32_t version = NSVersionOfLinkTimeLibrary("AppKit"); + if (version == -1) + { + // If we're loaded by an application that doesn't link against AppKit, + // use the runtime version instead. This check will not work for the + // case above. + version = NSVersionOfRunTimeLibrary("AppKit"); + } + + // Notice that this still works correctly even if version is -1. + return version >= 0x40e2400 /* version of 10.6 AppKit */; +} + +} // anonymous namespace + @interface wxOpenPanelDelegate : NSObject wxOSX_10_6_AND_LATER() { wxFileDialog* _dialog; @@ -62,7 +95,7 @@ - (id) init { - [super init]; + self = [super init]; _dialog = NULL; return self; } @@ -160,6 +193,15 @@ wxFileDialog::wxFileDialog( long style, const wxPoint& pos, const wxSize& sz, const wxString& name) : wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos, sz, name) { + m_filterIndex = -1; + m_sheetDelegate = [[ModalDialogDelegate alloc] init]; + [(ModalDialogDelegate*)m_sheetDelegate setImplementation: this]; + m_delegate = nil; +} + +wxFileDialog::~wxFileDialog() +{ + [m_sheetDelegate release]; } bool wxFileDialog::SupportsExtraControl() const @@ -304,10 +346,8 @@ void wxFileDialog::ShowWindowModal() [sPanel setAllowsOtherFileTypes:NO]; NSWindow* nativeParent = parentWindow->GetWXWindow(); - ModalDialogDelegate* sheetDelegate = [[ModalDialogDelegate alloc] init]; - [sheetDelegate setImplementation: this]; [sPanel beginSheetForDirectory:dir.AsNSString() file:file.AsNSString() - modalForWindow: nativeParent modalDelegate: sheetDelegate + modalForWindow: nativeParent modalDelegate: m_sheetDelegate didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: nil]; } @@ -325,11 +365,9 @@ void wxFileDialog::ShowWindowModal() [oPanel setAllowsMultipleSelection: (HasFlag(wxFD_MULTIPLE) ? YES : NO )]; 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 + modalDelegate: m_sheetDelegate didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: nil]; } @@ -360,7 +398,7 @@ wxWindow* wxFileDialog::CreateFilterPanel(wxWindow *extracontrol) if ( m_firstFileTypeFilter >= 0 ) m_filterChoice->SetSelection(m_firstFileTypeFilter); } - m_filterChoice->Connect(wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(wxFileDialog::OnFilterSelected), NULL, this); + m_filterChoice->Connect(wxEVT_CHOICE, wxCommandEventHandler(wxFileDialog::OnFilterSelected), NULL, this); } if(extracontrol) @@ -377,11 +415,8 @@ wxWindow* wxFileDialog::CreateFilterPanel(wxWindow *extracontrol) return extrapanel; } -// An item has been selected in the file filter wxChoice: -void wxFileDialog::OnFilterSelected( wxCommandEvent &WXUNUSED(event) ) +void wxFileDialog::DoOnFilterSelected(int index) { - int index = m_filterChoice->GetSelection(); - NSArray* types = GetTypesFromExtension(m_filterExtensions[index],m_currentExtensions); NSSavePanel* panel = (NSSavePanel*) GetWXWindow(); if ( m_delegate ) @@ -390,6 +425,12 @@ void wxFileDialog::OnFilterSelected( wxCommandEvent &WXUNUSED(event) ) [panel setAllowedFileTypes:types]; } +// An item has been selected in the file filter wxChoice: +void wxFileDialog::OnFilterSelected( wxCommandEvent &WXUNUSED(event) ) +{ + DoOnFilterSelected( m_filterChoice->GetSelection() ); +} + bool wxFileDialog::CheckFile( const wxString& filename ) { if ( m_currentExtensions.GetCount() == 0 ) @@ -408,6 +449,11 @@ bool wxFileDialog::CheckFile( const wxString& filename ) void wxFileDialog::SetupExtraControls(WXWindow nativeWindow) { NSSavePanel* panel = (NSSavePanel*) nativeWindow; + // for sandboxed app we cannot access the outer structures + // this leads to problems with extra controls, so as a temporary + // workaround for crashes we don't support those yet + if ( [panel contentView] == nil ) + return; wxNonOwnedWindow::Create( GetParent(), nativeWindow ); wxWindow* extracontrol = NULL; @@ -418,7 +464,6 @@ void wxFileDialog::SetupExtraControls(WXWindow nativeWindow) } NSView* accView = nil; - m_delegate = nil; if ( m_useFileTypeFilter ) { @@ -426,7 +471,7 @@ void wxFileDialog::SetupExtraControls(WXWindow nativeWindow) accView = m_filterPanel->GetHandle(); if( HasFlag(wxFD_OPEN) ) { - if ( 1 /* UMAGetSystemVersion() < 0x1060 */ ) + if ( UMAGetSystemVersion() < 0x1060 || !HasAppKit_10_6() ) { wxOpenPanelDelegate* del = [[wxOpenPanelDelegate alloc]init]; [del setFileDialog:this]; @@ -456,6 +501,12 @@ void wxFileDialog::SetupExtraControls(WXWindow nativeWindow) int wxFileDialog::ShowModal() { + WX_HOOK_MODAL_DIALOG(); + + wxCFEventLoopPauseIdleEvents pause; + + wxMacAutoreleasePool autoreleasepool; + wxCFStringRef cf( m_message ); wxCFStringRef dir( m_dir ); @@ -464,8 +515,6 @@ int wxFileDialog::ShowModal() m_path = wxEmptyString; m_fileNames.Clear(); m_paths.Clear(); - // since we don't support retrieving the matching filter - m_filterIndex = -1; wxNonOwnedWindow* parentWindow = NULL; int returnCode = -1; @@ -487,8 +536,13 @@ int wxFileDialog::ShowModal() } m_firstFileTypeFilter = -1; - - if ( m_useFileTypeFilter ) + + if ( m_useFileTypeFilter + && m_filterIndex >= 0 && m_filterIndex < m_filterExtensions.GetCount() ) + { + m_firstFileTypeFilter = m_filterIndex; + } + else if ( m_useFileTypeFilter ) { types = nil; bool useDefault = true; @@ -541,7 +595,20 @@ int wxFileDialog::ShowModal() { } - returnCode = [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ]; + /* + Let the file dialog know what file type should be used initially. + If this is not done then when setting the filter index + programmatically to 1 the file will still have the extension + of the first file type instead of the second one. E.g. when file + types are foo and bar, a filename "myletter" with SetDialogIndex(1) + would result in saving as myletter.foo, while we want myletter.bar. + */ + if(m_firstFileTypeFilter > 0) + { + DoOnFilterSelected(m_firstFileTypeFilter); + } + + returnCode = [sPanel runModalForDirectory: m_dir.IsEmpty() ? nil : dir.AsNSString() file:file.AsNSString() ]; ModalFinishedCallback(sPanel, returnCode); } else @@ -557,19 +624,22 @@ int wxFileDialog::ShowModal() [oPanel setMessage:cf.AsNSString()]; [oPanel setAllowsMultipleSelection: (HasFlag(wxFD_MULTIPLE) ? YES : NO )]; - if ( UMAGetSystemVersion() < 0x1060 ) +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + if ( UMAGetSystemVersion() >= 0x1060 && HasAppKit_10_6() ) { - returnCode = [oPanel runModalForDirectory:dir.AsNSString() - file:file.AsNSString() types:(m_delegate == nil ? types : nil)]; + [oPanel setAllowedFileTypes: (m_delegate == nil ? types : nil)]; + if ( !m_dir.IsEmpty() ) + [oPanel setDirectoryURL:[NSURL fileURLWithPath:dir.AsNSString() + isDirectory:YES]]; + returnCode = [oPanel runModal]; } else +#endif { - [oPanel setAllowedFileTypes: (m_delegate == nil ? types : nil)]; - [oPanel setDirectoryURL:[NSURL fileURLWithPath:dir.AsNSString() - isDirectory:YES]]; - returnCode = [oPanel runModal]; + returnCode = [oPanel runModalForDirectory:m_dir.IsEmpty() ? nil : dir.AsNSString() + file:file.AsNSString() types:(m_delegate == nil ? types : nil)]; } - + ModalFinishedCallback(oPanel, returnCode); } @@ -586,9 +656,13 @@ void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode) NSSavePanel* sPanel = (NSSavePanel*)panel; result = wxID_OK; - m_path = wxCFStringRef::AsString([sPanel filename]); + m_path = wxCFStringRef::AsStringWithNormalizationFormC([sPanel filename]); m_fileName = wxFileNameFromPath(m_path); m_dir = wxPathOnly( m_path ); + if (m_filterChoice) + { + m_filterIndex = m_filterChoice->GetSelection(); + } } } else @@ -601,7 +675,7 @@ void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode) NSArray* filenames = [oPanel filenames]; for ( size_t i = 0 ; i < [filenames count] ; ++ i ) { - wxString fnstr = wxCFStringRef::AsString([filenames objectAtIndex:i]); + wxString fnstr = wxCFStringRef::AsStringWithNormalizationFormC([filenames objectAtIndex:i]); m_paths.Add( fnstr ); m_fileNames.Add( wxFileNameFromPath(fnstr) ); if ( i == 0 ) @@ -624,7 +698,9 @@ void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode) if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL) SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED ); - UnsubclassWin(); + // workaround for sandboxed app, see above + if ( m_isNativeWindowWrapper ) + UnsubclassWin(); [(NSSavePanel*) panel setAccessoryView:nil]; }