OSX file dialog extensions (#2592)

Re-introduce OpenSavePanelDelegate for filtering when wildcard is provided (Spotlight search field was not working correctly, if extension was not known)
(and on macOS 10.11 allow programmatically showing the extra panel)

see http://www.github.com/wxWidgets/wxWidgets/pull/2592 and https://trac.wxwidgets.org/ticket/19324

co-authered-by: Jeff Young <jeff at rokeby dot ie>
This commit is contained in:
Stefan Csomor 2021-11-26 22:26:49 +01:00 committed by GitHub
parent c5f023a829
commit e765756555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 6 deletions

View File

@ -95,6 +95,7 @@ protected:
bool m_useFileTypeFilter; bool m_useFileTypeFilter;
int m_firstFileTypeFilter; int m_firstFileTypeFilter;
wxArrayString m_currentExtensions; wxArrayString m_currentExtensions;
WX_NSObject m_delegate;
#endif #endif
private: private:

View File

@ -41,6 +41,63 @@
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
// ============================================================================
// delegate for filtering by wildcard
// ============================================================================
@interface wxOpenSavePanelDelegate : NSObject<NSOpenSavePanelDelegate>
- (void)setAllowedExtensions:(const wxArrayString &)extensions;
@end
@implementation wxOpenSavePanelDelegate
{
wxArrayString m_extensions;
}
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url
{
if ( [url isFileURL] )
{
NSString* filename = [url path];
NSString* resolvedLink = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:filename error:nil];
if ( resolvedLink != nil )
filename = resolvedLink;
BOOL isDir = NO;
if( [[NSFileManager defaultManager]
fileExistsAtPath:filename isDirectory:&isDir] && isDir )
{
// allow ordinary folders to be enabled, but for packages apply our extensions check
if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
return YES; // it's a folder, OK to show
}
if ( m_extensions.GetCount() == 0 )
return YES;
NSString *ext = [filename pathExtension];
wxString wxext = wxCFStringRef([ext retain]).AsString().Lower();
for( const wxString& extension : m_extensions )
{
if( wxext == extension )
return YES;
}
}
return NO;
}
- (void)setAllowedExtensions:(const wxArrayString &)extensions
{
m_extensions = extensions;
}
@end
// ============================================================================ // ============================================================================
// implementation // implementation
// ============================================================================ // ============================================================================
@ -50,6 +107,7 @@ wxIMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase);
void wxFileDialog::Init() void wxFileDialog::Init()
{ {
m_filterIndex = -1; m_filterIndex = -1;
m_delegate = nil;
m_filterPanel = NULL; m_filterPanel = NULL;
m_filterChoice = NULL; m_filterChoice = NULL;
m_useFileTypeFilter = false; m_useFileTypeFilter = false;
@ -114,13 +172,14 @@ NSArray* GetTypesFromExtension( const wxString extensiongroup, wxArrayString& ex
return types; return types;
} }
NSArray* GetTypesFromFilter( const wxString& filter, wxArrayString& names, wxArrayString& extensiongroups ) NSArray* GetTypesFromFilter( const wxString& filter, wxArrayString& names, wxArrayString& extensiongroups, wxArrayString& allextensions )
{ {
NSMutableArray* types = nil; NSMutableArray* types = nil;
bool allowAll = false; bool allowAll = false;
names.Clear(); names.Clear();
extensiongroups.Clear(); extensiongroups.Clear();
allextensions.Clear();
if ( !filter.empty() ) if ( !filter.empty() )
{ {
@ -159,6 +218,8 @@ NSArray* GetTypesFromFilter( const wxString& filter, wxArrayString& names, wxArr
types = [[NSMutableArray alloc] init]; types = [[NSMutableArray alloc] init];
[types addObjectsFromArray:exttypes]; [types addObjectsFromArray:exttypes];
for( auto const& s : extensions )
allextensions.Add(s);
} }
} }
else else
@ -168,6 +229,8 @@ NSArray* GetTypesFromFilter( const wxString& filter, wxArrayString& names, wxArr
types = nil; types = nil;
} }
} }
if ( allowAll )
allextensions.Clear();
} }
[types autorelease]; [types autorelease];
return types; return types;
@ -188,7 +251,7 @@ void wxFileDialog::ShowWindowModal()
wxCHECK_RET(parentWindow, "Window modal display requires parent."); wxCHECK_RET(parentWindow, "Window modal display requires parent.");
NSArray* types = GetTypesFromFilter( m_wildCard, m_filterNames, m_filterExtensions ) ; NSArray* types = GetTypesFromFilter( m_wildCard, m_filterNames, m_filterExtensions, m_currentExtensions ) ;
if ( HasFlag(wxFD_SAVE) ) if ( HasFlag(wxFD_SAVE) )
{ {
NSSavePanel* sPanel = [NSSavePanel savePanel]; NSSavePanel* sPanel = [NSSavePanel savePanel];
@ -319,6 +382,12 @@ void wxFileDialog::DoOnFilterSelected(int index)
{ {
NSArray* types = GetTypesFromExtension(m_filterExtensions[index],m_currentExtensions); NSArray* types = GetTypesFromExtension(m_filterExtensions[index],m_currentExtensions);
NSSavePanel* panel = (NSSavePanel*) GetWXWindow(); NSSavePanel* panel = (NSSavePanel*) GetWXWindow();
if ( m_delegate )
{
[(wxOpenSavePanelDelegate*)m_delegate setAllowedExtensions:m_currentExtensions];
[panel validateVisibleColumns];
}
else
[panel setAllowedFileTypes:types]; [panel setAllowedFileTypes:types];
m_currentlySelectedFilterIndex = index; m_currentlySelectedFilterIndex = index;
@ -368,6 +437,10 @@ void wxFileDialog::SetupExtraControls(WXWindow nativeWindow)
{ {
[accView removeFromSuperview]; [accView removeFromSuperview];
[panel setAccessoryView:accView]; [panel setAccessoryView:accView];
if ([panel respondsToSelector:@selector(setAccessoryViewDisclosed)])
{
[panel setAccessoryViewDisclosed:YES];
}
} }
else else
{ {
@ -431,7 +504,7 @@ int wxFileDialog::ShowModal()
} }
NSArray* types = GetTypesFromFilter( m_wildCard, m_filterNames, m_filterExtensions ) ; NSArray* types = GetTypesFromFilter( m_wildCard, m_filterNames, m_filterExtensions, m_currentExtensions ) ;
m_useFileTypeFilter = m_filterExtensions.GetCount() > 1; m_useFileTypeFilter = m_filterExtensions.GetCount() > 1;
@ -512,6 +585,10 @@ int wxFileDialog::ShowModal()
SetupExtraControls(oPanel); SetupExtraControls(oPanel);
wxOpenSavePanelDelegate* del = [[wxOpenSavePanelDelegate alloc]init];
[oPanel setDelegate:del];
m_delegate = del;
[oPanel setTreatsFilePackagesAsDirectories:NO]; [oPanel setTreatsFilePackagesAsDirectories:NO];
[oPanel setCanChooseDirectories:NO]; [oPanel setCanChooseDirectories:NO];
[oPanel setResolvesAliases:HasFlag(wxFD_NO_FOLLOW) ? NO : YES]; [oPanel setResolvesAliases:HasFlag(wxFD_NO_FOLLOW) ? NO : YES];
@ -530,6 +607,9 @@ int wxFileDialog::ShowModal()
} }
else else
{ {
if ( m_delegate )
[(wxOpenSavePanelDelegate*) m_delegate setAllowedExtensions: m_currentExtensions];
else
[oPanel setAllowedFileTypes: types]; [oPanel setAllowedFileTypes: types];
} }
if ( !m_dir.IsEmpty() ) if ( !m_dir.IsEmpty() )
@ -595,6 +675,12 @@ void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode)
else else
m_filterIndex = GetMatchingFilterExtension(m_fileName); m_filterIndex = GetMatchingFilterExtension(m_fileName);
} }
if ( m_delegate )
{
[oPanel setDelegate:nil];
[m_delegate release];
m_delegate = nil;
}
} }
SetReturnCode(result); SetReturnCode(result);