+// - as setAllowedFileTypes is only functional for NSOpenPanel on 10.6+, on earlier systems, the file
+// type choice will not be shown, but all possible file items will be shown, if a popup must be working
+// 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(<NSOpenSavePanelDelegate>)
+{
+ wxFileDialog* _dialog;
+}
+
+- (wxFileDialog*) fileDialog;
+- (void) setFileDialog:(wxFileDialog*) dialog;
+
+- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
+
+@end
+
+@implementation wxOpenPanelDelegate
+
+- (id) init
+{
+ self = [super init];
+ _dialog = NULL;
+ return self;
+}
+
+- (wxFileDialog*) fileDialog
+{
+ return _dialog;
+}
+
+- (void) setFileDialog:(wxFileDialog*) dialog
+{
+ _dialog = dialog;
+}
+
+- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
+{
+ BOOL showObject = YES;
+
+ NSString* resolvedLink = [[NSFileManager defaultManager] pathContentOfSymbolicLinkAtPath:filename];
+ if ( resolvedLink != nil )
+ filename = resolvedLink;
+
+ NSDictionary* fileAttribs = [[NSFileManager defaultManager]
+ fileAttributesAtPath:filename traverseLink:YES];
+ if (fileAttribs)
+ {
+ // check for packages
+ if ([NSFileTypeDirectory isEqualTo:[fileAttribs objectForKey:NSFileType]])
+ {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
+ showObject = YES; // it's a folder, OK to show
+ else
+ {
+ // it's a packaged directory, apply check
+ wxCFStringRef filecf([filename retain]);
+ showObject = _dialog->CheckFile(filecf.AsString());
+ }
+ }
+ else
+ {
+ // the code above only solves links, not aliases, do this here:
+
+ NSString* resolvedAlias = nil;
+
+ CFURLRef url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
+ (CFStringRef)filename,
+ kCFURLPOSIXPathStyle,
+ NO);
+ if (url != NULL)
+ {
+ FSRef fsRef;
+ if (CFURLGetFSRef(url, &fsRef))
+ {
+ Boolean targetIsFolder, wasAliased;
+ OSErr err = FSResolveAliasFile (&fsRef, true, &targetIsFolder, &wasAliased);
+
+ if ((err == noErr) && wasAliased)
+ {
+ CFURLRef resolvedUrl = CFURLCreateFromFSRef(kCFAllocatorDefault, &fsRef);
+ if (resolvedUrl != NULL)
+ {
+ resolvedAlias = (NSString*) CFURLCopyFileSystemPath(resolvedUrl,
+ kCFURLPOSIXPathStyle);
+ CFRelease(resolvedUrl);
+ }
+ }
+ }
+ CFRelease(url);
+ }
+
+ if (resolvedAlias != nil)
+ {
+ // recursive call
+ [resolvedAlias autorelease];
+ showObject = [self panel:sender shouldShowFilename:resolvedAlias];
+ }
+ else
+ {
+ wxCFStringRef filecf([filename retain]);
+ showObject = _dialog->CheckFile(filecf.AsString());
+ }
+ }
+ }
+
+ return showObject;
+}
+
+@end