blob: 7dc820266c27148c16c9531c76d1f5d492f72522 [file] [log] [blame]
/*
* 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 <sys/stat.h>
#import <Cocoa/Cocoa.h>
#import <JavaNativeFoundation/JavaNativeFoundation.h>
#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)finalize { [super finalize]; }
- (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];
}
[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
CFStringRef filePath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle);
BOOL shouldEnableFile = [self askFilenameFilter:(NSString *)filePath];
CFRelease(filePath);
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;
}