]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/cocoa/filedlg.mm
Since wxDialog::Show(false) only calls wxWindow::Show, we must explicitly hide the...
[wxWidgets.git] / src / osx / cocoa / filedlg.mm
index c212ecea36b3046b63079136db86e3f146aabd78..fd87e5b38594501ad2cd4d44387d897e61be1f33 100644 (file)
@@ -30,6 +30,7 @@
 #endif
 
 #include "wx/filename.h"
+#include "wx/tokenzr.h"
 
 #include "wx/osx/private.h"
 
 // implementation
 // ============================================================================
 
+// Open Items:
+// - support for old style MacOS creator / type combos
+// - parameter support for descending into packages as directories (setTreatsFilePackagesAsDirectories)
+
 IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase)
 
 wxFileDialog::wxFileDialog(
@@ -47,7 +52,6 @@ wxFileDialog::wxFileDialog(
 {
 }
 
-
 NSArray* GetTypesFromFilter( const wxString filter )
 {
     NSMutableArray* types = nil;
@@ -99,78 +103,82 @@ NSArray* GetTypesFromFilter( const wxString filter )
         const size_t extCount = extensions.GetCount();
         for ( size_t i = 0 ; i < extCount; i++ )
         {
-            wxString extension = extensions[i];
+            wxString extensiongroup = extensions[i];
+            wxStringTokenizer tokenizer( extensiongroup , wxT(";") ) ;
+            while ( tokenizer.HasMoreTokens() )
+            {
+                wxString extension = tokenizer.GetNextToken() ;
+                // Remove leading '*'
+                if (extension.length() && (extension.GetChar(0) == '*'))
+                    extension = extension.Mid( 1 );
 
-            // Remove leading '*'
-            if (extension.length() && (extension.GetChar(0) == '*'))
-                extension = extension.Mid( 1 );
+                // Remove leading '.'
+                if (extension.length() && (extension.GetChar(0) == '.'))
+                    extension = extension.Mid( 1 );
 
-            // Remove leading '.'
-            if (extension.length() && (extension.GetChar(0) == '.'))
-                extension = extension.Mid( 1 );
-
-            if ( extension.IsEmpty() )
-            {
-                if ( types != nil )
-                    [types release];
-                return nil;
-            }
+                // Remove leading '*', this is for handling *.*
+                if (extension.length() && (extension.GetChar(0) == '*'))
+                    extension = extension.Mid( 1 );
 
+                if ( extension.IsEmpty() )
+                {
+                    if ( types != nil )
+                        [types release];
+                    return nil;
+                }
 
-            if ( types == nil )
-                types = [[NSMutableArray alloc] init];
+                if ( types == nil )
+                    types = [[NSMutableArray alloc] init];
 
-            wxCFStringRef cfext(extension);
-            [types addObject: (NSString*)cfext.AsNSString()  ];
+                wxCFStringRef cfext(extension);
+                [types addObject: (NSString*)cfext.AsNSString()  ];
 #if 0
-            wxUint32 fileType, creator;
-
-            // extension -> mactypes
+                // add support for classic fileType / creator here
+                wxUint32 fileType, creator;
+                // extension -> mactypes
 #endif
+            }
+
         }
     }
     return types;
 }
 
-int wxFileDialog::ShowModal()
+void wxFileDialog::ShowWindowModal()
 {
-    int result = wxID_CANCEL;
-
-    NSSavePanel *panel = nil;
-
     wxCFStringRef cf( m_message );
-
     wxCFStringRef dir( m_dir );
     wxCFStringRef file( m_fileName );
 
-    m_path = wxEmptyString;
-    m_fileNames.Clear();
+    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];
-
-        if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
-        {
-        }
-
-        if ( [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ] == NSOKButton )
-        {
-            panel = sPanel;
-            result = wxID_OK;
-
-            wxCFStringRef filename( [[sPanel filename] retain] );
-
-            m_path = filename.AsString();
-            m_fileName = wxFileNameFromPath(m_path);
-            m_dir = wxPathOnly( m_path );
-        }
+        [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
+    else 
     {
         NSArray* types = GetTypesFromFilter( m_wildCard ) ;
         NSOpenPanel* oPanel = [NSOpenPanel openPanel];
@@ -179,208 +187,122 @@ int wxFileDialog::ShowModal()
         [oPanel setResolvesAliases:YES];
         [oPanel setCanChooseFiles:YES];
         [oPanel setMessage:cf.AsNSString()];
-
-        if ( [oPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() types:types] == NSOKButton )
-        {
-            panel = oPanel;
-            result = wxID_OK;
-            NSArray* filenames = [oPanel filenames];
-            for ( size_t i = 0 ; i < [filenames count] ; ++ i )
-            {
-                wxCFStringRef filename( [(NSString*) [filenames objectAtIndex:i] retain] );
-                wxString fnstr = filename.AsString();
-                m_paths.Add( fnstr );
-                m_fileNames.Add( wxFileNameFromPath(fnstr) );
-                if ( i == 0 )
-                {
-                    m_path = fnstr;
-                    m_fileName = wxFileNameFromPath(fnstr);
-                    m_dir = wxPathOnly( fnstr );
-                }
-            }
-        }
-        if ( types != nil )
-            [types release];
+    
+        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];
     }
-
-    return result;
 }
 
-#if 0
+int wxFileDialog::ShowModal()
+{
+    NSSavePanel *panel = nil;
 
-    wxASSERT(CreateBase(parent,wxID_ANY,pos,wxDefaultSize,style,wxDefaultValidator,wxDialogNameStr));
+    wxCFStringRef cf( m_message );
 
-    if ( parent )
-        parent->AddChild(this);
+    wxCFStringRef dir( m_dir );
+    wxCFStringRef file( m_fileName );
 
-    m_cocoaNSWindow = nil;
-    m_cocoaNSView = nil;
+    m_path = wxEmptyString;
+    m_fileNames.Clear();
+    m_paths.Clear();
+    // since we don't support retrieving the matching filter
+    m_filterIndex = -1;
 
-    //Init the wildcard array
-    m_wildcards = [[NSMutableArray alloc] initWithCapacity:0];
+    wxNonOwnedWindow* parentWindow = NULL;
+    int returnCode = -1;
 
-    //If the user requests to save - use a NSSavePanel
-    //else use a NSOpenPanel
-    if (HasFlag(wxFD_SAVE))
+    if (GetParent())
     {
-        SetNSPanel([NSSavePanel savePanel]);
-
-        [GetNSSavePanel() setTitle:wxNSStringWithWxString(message)];
-
-        [GetNSSavePanel() setPrompt:@"Save"];
-        [GetNSSavePanel() setTreatsFilePackagesAsDirectories:YES];
-        [GetNSSavePanel() setCanSelectHiddenExtension:YES];
-
-//        Cached as per-app in obj-c
-//        [GetNSSavePanel() setExtensionHidden:YES];
-
-        //
-        // NB:  Note that only Panther supports wildcards
-        // with save dialogs - not that wildcards in save
-        // dialogs are all that useful, anyway :)
-        //
+        parentWindow = dynamic_cast<wxNonOwnedWindow*>(wxGetTopLevelParent(GetParent()));
     }
-    else //m_dialogStyle & wxFD_OPEN
-    {
-        SetNSPanel([NSOpenPanel openPanel]);
-        [m_cocoaNSWindow setTitle:wxNSStringWithWxString(message)];
-
-        [(NSOpenPanel*)m_cocoaNSWindow setAllowsMultipleSelection:(HasFlag(wxFD_MULTIPLE))];
-        [(NSOpenPanel*)m_cocoaNSWindow setResolvesAliases:YES];
-        [(NSOpenPanel*)m_cocoaNSWindow setCanChooseFiles:YES];
-        [(NSOpenPanel*)m_cocoaNSWindow setCanChooseDirectories:NO];
-        [GetNSSavePanel() setPrompt:@"Open"];
-
-        //convert wildcards - open panel only takes file extensions -
-        //no actual wildcards here :)
-        size_t lastwcpos = 0;
-        bool bDescription = true;
-        size_t i;
-        for(i = wildCard.find('|');
-                i != wxString::npos;
-                i = wildCard.find('|', lastwcpos+1))
-        {
-            size_t oldi = i;
-
-            if(!bDescription)
-            {
-                bDescription = !bDescription;
 
-                //work backwards looking for a period
-                while(i != lastwcpos && wildCard[--i] != '.') {}
-
-                if(i == lastwcpos)
-                {
-                    //no extension - can't use this wildcard
-                    lastwcpos = oldi;
-                    continue;
-                }
-
-                [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
-            }
-            else
-                bDescription = !bDescription;
-            lastwcpos = oldi;
-        }
+    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];
 
-        if (!bDescription)
+        if ( HasFlag(wxFD_OVERWRITE_PROMPT) )
         {
-            //get last wildcard
-            size_t oldi = wildCard.length();
-            i = oldi;
-
-            //work backwards looking for a period
-            while(i != lastwcpos && wildCard[--i] != '.') {}
-
-            if(i != lastwcpos)
-                [m_wildcards addObject:wxNSStringWithWxString(wildCard.substr(i+1, oldi-i-1))];
         }
 
-        if ([m_wildcards count] == 0)
-        {
-            [m_wildcards release];
-            m_wildcards = nil;
-        }
+        returnCode = [sPanel runModalForDirectory:dir.AsNSString() file:file.AsNSString() ];
+        ModalFinishedCallback(sPanel, returnCode);
     }
-}
-
-wxFileDialog::~wxFileDialog()
-{
-    [m_wildcards release];
-}
-
-void wxFileDialog::GetPaths(wxArrayString& paths) const
-{
-    paths.Empty();
+    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()];
 
-    wxString dir(m_dir);
-    if ( m_dir.Last() != _T('\\') )
-        dir += _T('\\');
+        returnCode = [oPanel runModalForDirectory:dir.AsNSString()
+                        file:file.AsNSString() types:types];
 
-    size_t count = m_fileNames.GetCount();
-    for ( size_t n = 0; n < count; n++ )
-    {
-        if (wxFileName(m_fileNames[n]).IsAbsolute())
-            paths.Add(m_fileNames[n]);
-        else
-            paths.Add(dir + m_fileNames[n]);
+        ModalFinishedCallback(oPanel, returnCode);
+        
+        if ( types != nil )
+            [types release];
     }
-}
 
-void wxFileDialog::GetFilenames(wxArrayString& files) const
-{
-    files = m_fileNames;
+    return GetReturnCode();
 }
 
-void wxFileDialog::SetPath(const wxString& path)
+void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode)
 {
-    wxString ext;
-    wxFileName::SplitPath(path, &m_dir, &m_fileName, &ext);
-    if ( !ext.empty() )
-        m_fileName << _T('.') << ext;
-}
-
-int wxFileDialog::ShowModal()
-{
-    wxAutoNSAutoreleasePool thePool;
-
-    m_fileNames.Empty();
-
-    int nResult;
-
+    int result = wxID_CANCEL;
     if (HasFlag(wxFD_SAVE))
     {
-        nResult = [GetNSSavePanel()
-                    runModalForDirectory:wxNSStringWithWxString(m_dir)
-                    file:wxNSStringWithWxString(m_fileName)];
-
-        if (nResult == NSOKButton)
+        if (returnCode == NSOKButton )
         {
-            m_fileNames.Add(wxStringWithNSString([GetNSSavePanel() filename]));
-            m_path = m_fileNames[0];
+            NSSavePanel* sPanel = (NSSavePanel*)panel;
+            result = wxID_OK;
+
+            m_path = wxCFStringRef::AsString([sPanel filename]);
+            m_fileName = wxFileNameFromPath(m_path);
+            m_dir = wxPathOnly( m_path );
         }
     }
-    else //m_dialogStyle & wxFD_OPEN
+    else
     {
-        nResult = [(NSOpenPanel*)m_cocoaNSWindow
-                    runModalForDirectory:wxNSStringWithWxString(m_dir)
-                    file:wxNSStringWithWxString(m_fileName)
-                    types:m_wildcards];
-
-        if (nResult == NSOKButton)
+        NSOpenPanel* oPanel = (NSOpenPanel*)panel;
+        if (returnCode == NSOKButton )
         {
-            for(unsigned i = 0; i < [[(NSOpenPanel*)m_cocoaNSWindow filenames] count]; ++i)
+            panel = oPanel;
+            result = wxID_OK;
+            NSArray* filenames = [oPanel filenames];
+            for ( size_t i = 0 ; i < [filenames count] ; ++ i )
             {
-                m_fileNames.Add(wxStringWithNSString([[(NSOpenPanel*)m_cocoaNSWindow filenames] objectAtIndex:(i)]));
+                wxString fnstr = wxCFStringRef::AsString([filenames objectAtIndex:i]);
+                m_paths.Add( fnstr );
+                m_fileNames.Add( wxFileNameFromPath(fnstr) );
+                if ( i == 0 )
+                {
+                    m_path = fnstr;
+                    m_fileName = wxFileNameFromPath(fnstr);
+                    m_dir = wxPathOnly( fnstr );
+                }
             }
-
-            m_path = m_fileNames[0];
         }
     }
-
-    return nResult == NSOKButton ? wxID_OK : wxID_CANCEL;
+    SetReturnCode(result);
+    
+    if (GetModality() == wxDIALOG_MODALITY_WINDOW_MODAL)
+        SendWindowModalDialogEvent ( wxEVT_WINDOW_MODAL_DIALOG_CLOSED  );
 }
 
-#endif
-
 #endif // wxUSE_FILEDLG