/* * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #import #import #import #import "CFileDialog.h" #import "ThreadUtilities.h" #import "java_awt_FileDialog.h" #import "sun_lwawt_macosx_CFileDialog.h" @implementation CFileDialog - (id)initWithFilter:(jboolean)inHasFilter fileDialog:(jobject)inDialog title:(NSString *)inTitle directory:(NSString *)inPath file:(NSString *)inFile mode:(jint)inMode multipleMode:(BOOL)inMultipleMode shouldNavigate:(BOOL)inNavigateApps canChooseDirectories:(BOOL)inChooseDirectories withEnv:(JNIEnv*)env; { if (self == [super init]) { fHasFileFilter = inHasFilter; fFileDialog = JNFNewGlobalRef(env, inDialog); fDirectory = inPath; [fDirectory retain]; fFile = inFile; [fFile retain]; fTitle = inTitle; [fTitle retain]; fMode = inMode; fMultipleMode = inMultipleMode; fNavigateApps = inNavigateApps; fChooseDirectories = inChooseDirectories; fPanelResult = NSCancelButton; } return self; } -(void) disposer { if (fFileDialog != NULL) { JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; JNFDeleteGlobalRef(env, fFileDialog); fFileDialog = NULL; } } -(void) dealloc { [fDirectory release]; fDirectory = nil; [fFile release]; fFile = nil; [fTitle release]; fTitle = nil; [fURLs release]; fURLs = nil; [super dealloc]; } - (void)safeSaveOrLoad { NSSavePanel *thePanel = nil; /* * 8013553: turns off extension hiding for the native file dialog. * This way is used because setExtensionHidden(NO) doesn't work * as expected. */ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setBool:NO forKey:@"NSNavLastUserSetHideExtensionButtonState"]; if (fMode == java_awt_FileDialog_SAVE) { thePanel = [NSSavePanel savePanel]; [thePanel setAllowsOtherFileTypes:YES]; } else { thePanel = [NSOpenPanel openPanel]; } if (thePanel != nil) { [thePanel setTitle:fTitle]; if (fNavigateApps) { [thePanel setTreatsFilePackagesAsDirectories:YES]; } if (fMode == java_awt_FileDialog_LOAD) { NSOpenPanel *openPanel = (NSOpenPanel *)thePanel; [openPanel setAllowsMultipleSelection:fMultipleMode]; [openPanel setCanChooseFiles:!fChooseDirectories]; [openPanel setCanChooseDirectories:fChooseDirectories]; [openPanel setCanCreateDirectories:YES]; if (fChooseDirectories) { NSString *buttonPrompt = NSLocalizedString(@ " Choose ", @ " Choose " ); if (buttonPrompt == nil) { buttonPrompt = @ " Choose " ; } [openPanel setPrompt:buttonPrompt]; } } [thePanel setDelegate:self]; fPanelResult = [thePanel runModalForDirectory:fDirectory file:fFile]; [thePanel setDelegate:nil]; if ([self userClickedOK]) { if (fMode == java_awt_FileDialog_LOAD) { NSOpenPanel *openPanel = (NSOpenPanel *)thePanel; fURLs = [openPanel URLs]; } else { fURLs = [NSArray arrayWithObject:[thePanel URL]]; } [fURLs retain]; } } [self disposer]; } - (BOOL) askFilenameFilter:(NSString *)filename { JNIEnv *env = [ThreadUtilities getJNIEnv]; jstring jString = JNFNormalizedJavaStringForPath(env, filename); static JNF_CLASS_CACHE(jc_CFileDialog, "sun/lwawt/macosx/CFileDialog"); static JNF_MEMBER_CACHE(jm_queryFF, jc_CFileDialog, "queryFilenameFilter", "(Ljava/lang/String;)Z"); BOOL returnValue = JNFCallBooleanMethod(env, fFileDialog, jm_queryFF, jString); // AWT_THREADING Safe (AWTRunLoopMode) (*env)->DeleteLocalRef(env, jString); return returnValue; } - (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url { if (!fHasFileFilter) return YES; // no filter, no problem! // check if it's not a normal file NSNumber *isFile = nil; if ([url getResourceValue:&isFile forKey:NSURLIsRegularFileKey error:nil]) { if (![isFile boolValue]) return YES; // always show directories and non-file entities (browsing servers/mounts, etc) } // if in directory-browsing mode, don't offer files if ((fMode != java_awt_FileDialog_LOAD) && (fMode != java_awt_FileDialog_SAVE)) { return NO; } // ask the file filter up in Java NSString* filePath = (NSString*)CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle); BOOL shouldEnableFile = [self askFilenameFilter:filePath]; [filePath release]; return shouldEnableFile; } - (BOOL) userClickedOK { return fPanelResult == NSOKButton; } - (NSArray *)URLs { return [[fURLs retain] autorelease]; } @end /* * Class: sun_lwawt_macosx_CFileDialog * Method: nativeRunFileDialog * Signature: (Ljava/lang/String;ILjava/io/FilenameFilter; * Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_sun_lwawt_macosx_CFileDialog_nativeRunFileDialog (JNIEnv *env, jobject peer, jstring title, jint mode, jboolean multipleMode, jboolean navigateApps, jboolean chooseDirectories, jboolean hasFilter, jstring directory, jstring file) { jobjectArray returnValue = NULL; JNF_COCOA_ENTER(env); NSString *dialogTitle = JNFJavaToNSString(env, title); if ([dialogTitle length] == 0) { dialogTitle = @" "; } CFileDialog *dialogDelegate = [[CFileDialog alloc] initWithFilter:hasFilter fileDialog:peer title:dialogTitle directory:JNFJavaToNSString(env, directory) file:JNFJavaToNSString(env, file) mode:mode multipleMode:multipleMode shouldNavigate:navigateApps canChooseDirectories:chooseDirectories withEnv:env]; [JNFRunLoop performOnMainThread:@selector(safeSaveOrLoad) on:dialogDelegate withObject:nil waitUntilDone:YES]; if ([dialogDelegate userClickedOK]) { NSArray *urls = [dialogDelegate URLs]; jsize count = [urls count]; static JNF_CLASS_CACHE(jc_String, "java/lang/String"); returnValue = JNFNewObjectArray(env, &jc_String, count); [urls enumerateObjectsUsingBlock:^(id url, NSUInteger index, BOOL *stop) { jstring filename = JNFNormalizedJavaStringForPath(env, [url path]); (*env)->SetObjectArrayElement(env, returnValue, index, filename); (*env)->DeleteLocalRef(env, filename); }]; } [dialogDelegate release]; JNF_COCOA_EXIT(env); return returnValue; }