mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-27 03:46:17 -06:00
System File Chooser: added "Format" combobox on macOS (if using more than one filter)
This commit is contained in:
@@ -21,6 +21,8 @@ extern "C" {
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_resolvesAliases 4L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsMultipleSelection
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsMultipleSelection 8L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_accessoryViewDisclosed
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_accessoryViewDisclosed 16L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showsTagField
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showsTagField 256L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canCreateDirectories
|
||||
@@ -35,6 +37,8 @@ extern "C" {
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsOtherFileTypes 8192L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_treatsFilePackagesAsDirectories
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_treatsFilePackagesAsDirectories 16384L
|
||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showSingleFilterField
|
||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showSingleFilterField 16777216L
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: setWindowRoundedBorder
|
||||
@@ -78,10 +82,10 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_togg
|
||||
/*
|
||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||
* Method: showFileChooser
|
||||
* Signature: (ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II[Ljava/lang/String;)[Ljava/lang/String;
|
||||
* Signature: (ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;III[Ljava/lang/String;)[Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showFileChooser
|
||||
(JNIEnv *, jclass, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobjectArray);
|
||||
(JNIEnv *, jclass, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jint, jobjectArray);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -26,6 +26,80 @@
|
||||
* @since 3.6
|
||||
*/
|
||||
|
||||
//---- class FileChooserDelegate ----------------------------------------------
|
||||
|
||||
@interface FileChooserDelegate : NSObject {
|
||||
NSArray* _filters;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign) NSSavePanel* dialog;
|
||||
|
||||
- (void)initFilterAccessoryView: (NSMutableArray*)filters :(int)filterIndex
|
||||
:(NSString*)filterFieldLabel :(bool)showSingleFilterField;
|
||||
- (void)selectFormat: (id)sender;
|
||||
- (void)selectFormatAtIndex: (int)index;
|
||||
@end
|
||||
|
||||
@implementation FileChooserDelegate
|
||||
|
||||
- (void)initFilterAccessoryView: (NSMutableArray*)filters :(int)filterIndex
|
||||
:(NSString*)filterFieldLabel :(bool)showSingleFilterField
|
||||
{
|
||||
_filters = filters;
|
||||
|
||||
// get filter names
|
||||
NSArray* filterNames = filters.lastObject;
|
||||
[filters removeLastObject];
|
||||
|
||||
// do not add filter/format combobox if there is only one filter
|
||||
if( filters.count <= 1 && !showSingleFilterField ) {
|
||||
[self selectFormatAtIndex:0];
|
||||
return;
|
||||
}
|
||||
|
||||
// create label
|
||||
NSTextField* label = [[NSTextField alloc] initWithFrame:NSMakeRect( 0, 0, 60, 22 )];
|
||||
label.stringValue = (filterFieldLabel != NULL) ? filterFieldLabel : @"Format:";
|
||||
label.editable = NO;
|
||||
label.bordered = NO;
|
||||
label.bezeled = NO;
|
||||
label.drawsBackground = NO;
|
||||
|
||||
// create combobox
|
||||
NSPopUpButton* popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect( 50, 2, 140, 22 ) pullsDown:NO];
|
||||
[popupButton addItemsWithTitles:filterNames];
|
||||
[popupButton selectItemAtIndex:MIN( MAX( filterIndex, 0 ), filterNames.count - 1 )];
|
||||
[popupButton setTarget:self];
|
||||
[popupButton setAction:@selector(selectFormat:)];
|
||||
|
||||
// create view
|
||||
NSView* accessoryView = [[NSView alloc] initWithFrame:NSMakeRect( 0, 0, 200, 32 )];
|
||||
[accessoryView addSubview:label];
|
||||
[accessoryView addSubview:popupButton];
|
||||
|
||||
[_dialog setAccessoryView:accessoryView];
|
||||
|
||||
// initial filter
|
||||
[self selectFormatAtIndex:filterIndex];
|
||||
}
|
||||
|
||||
- (void)selectFormat:(id)sender {
|
||||
NSPopUpButton* popupButton = (NSPopUpButton*) sender;
|
||||
[self selectFormatAtIndex:popupButton.indexOfSelectedItem];
|
||||
}
|
||||
|
||||
- (void)selectFormatAtIndex: (int)index {
|
||||
index = MIN( MAX( index, 0 ), _filters.count - 1 );
|
||||
NSArray* fileTypes = [_filters objectAtIndex:index];
|
||||
|
||||
// use deprecated allowedFileTypes instead of newer allowedContentTypes (since macOS 11+)
|
||||
// to support older macOS versions 10.14+ and because of some problems with allowedContentTypes:
|
||||
// https://github.com/chromium/chromium/blob/d8e0032963b7ca4728ff4117933c0feb3e479b7a/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm#L209-232
|
||||
_dialog.allowedFileTypes = [fileTypes containsObject:@"*"] ? nil : fileTypes;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//---- helper -----------------------------------------------------------------
|
||||
|
||||
#define isOptionSet( option ) ((optionsSet & com_formdev_flatlaf_ui_FlatNativeMacLibrary_ ## option) != 0)
|
||||
@@ -40,14 +114,55 @@ jobjectArray newJavaStringArray( JNIEnv* env, jsize count ) {
|
||||
return env->NewObjectArray( count, stringClass, NULL );
|
||||
}
|
||||
|
||||
static NSMutableArray* initFilters( JNIEnv* env, jobjectArray fileTypes ) {
|
||||
jint length = env->GetArrayLength( fileTypes );
|
||||
if( length <= 0 )
|
||||
return NULL;
|
||||
|
||||
NSMutableArray* filterNames = [NSMutableArray array];
|
||||
NSMutableArray* filters = [NSMutableArray array];
|
||||
NSString* filterName = NULL;
|
||||
NSMutableArray* filter = NULL;
|
||||
for( int i = 0; i < length; i++ ) {
|
||||
jstring jstr = (jstring) env->GetObjectArrayElement( fileTypes, i );
|
||||
if( jstr == NULL ) {
|
||||
if( filter != NULL ) {
|
||||
if( filter.count > 0 ) {
|
||||
[filterNames addObject:filterName];
|
||||
[filters addObject:filter];
|
||||
}
|
||||
filterName = NULL;
|
||||
filter = NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString* str = JavaToNSString( env, jstr );
|
||||
env->DeleteLocalRef( jstr );
|
||||
if( filter == NULL ) {
|
||||
filterName = str;
|
||||
filter = [NSMutableArray array];
|
||||
} else
|
||||
[filter addObject:str];
|
||||
}
|
||||
|
||||
if( filters.count == 0 )
|
||||
return NULL;
|
||||
|
||||
// add filter names to array (removed again after creating combobox)
|
||||
[filters addObject:filterNames];
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
//---- JNI methods ------------------------------------------------------------
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showFileChooser
|
||||
( JNIEnv* env, jclass cls, jboolean open,
|
||||
jstring title, jstring prompt, jstring message, jstring nameFieldLabel,
|
||||
jstring nameFieldStringValue, jstring directoryURL,
|
||||
jint optionsSet, jint optionsClear, jobjectArray allowedFileTypes )
|
||||
jstring title, jstring prompt, jstring message, jstring filterFieldLabel,
|
||||
jstring nameFieldLabel, jstring nameFieldStringValue, jstring directoryURL,
|
||||
jint optionsSet, jint optionsClear, jint fileTypeIndex, jobjectArray fileTypes )
|
||||
{
|
||||
JNI_COCOA_ENTER()
|
||||
|
||||
@@ -55,21 +170,11 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_
|
||||
NSString* nsTitle = JavaToNSString( env, title );
|
||||
NSString* nsPrompt = JavaToNSString( env, prompt );
|
||||
NSString* nsMessage = JavaToNSString( env, message );
|
||||
NSString* nsFilterFieldLabel = JavaToNSString( env, filterFieldLabel );
|
||||
NSString* nsNameFieldLabel = JavaToNSString( env, nameFieldLabel );
|
||||
NSString* nsNameFieldStringValue = JavaToNSString( env, nameFieldStringValue );
|
||||
NSString* nsDirectoryURL = JavaToNSString( env, directoryURL );
|
||||
|
||||
NSArray* nsAllowedFileTypes = NULL;
|
||||
jsize len = env->GetArrayLength( allowedFileTypes );
|
||||
if( len > 0 ) {
|
||||
NSMutableArray* nsArray = [NSMutableArray arrayWithCapacity:len];
|
||||
for( int i = 0; i < len; i++ ) {
|
||||
jstring str = (jstring) env->GetObjectArrayElement( allowedFileTypes, i );
|
||||
nsArray[i] = JavaToNSString( env, str );
|
||||
env->DeleteLocalRef( str );
|
||||
}
|
||||
nsAllowedFileTypes = nsArray;
|
||||
}
|
||||
NSMutableArray* filters = initFilters( env, fileTypes );
|
||||
|
||||
NSArray* urls = NULL;
|
||||
NSArray** purls = &urls;
|
||||
@@ -93,6 +198,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_
|
||||
if( nsDirectoryURL != NULL )
|
||||
dialog.directoryURL = [NSURL fileURLWithPath:nsDirectoryURL isDirectory:YES];
|
||||
|
||||
// set open options
|
||||
if( open ) {
|
||||
NSOpenPanel* openDialog = (NSOpenPanel*) dialog;
|
||||
|
||||
@@ -109,6 +215,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_
|
||||
openDialog.allowsMultipleSelection = isOptionSet( FC_allowsMultipleSelection );
|
||||
}
|
||||
|
||||
// set options
|
||||
if( isOptionSetOrClear( FC_showsTagField ) )
|
||||
dialog.showsTagField = isOptionSet( FC_showsTagField );
|
||||
if( isOptionSetOrClear( FC_canCreateDirectories ) )
|
||||
@@ -124,13 +231,21 @@ JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_
|
||||
if( isOptionSetOrClear( FC_treatsFilePackagesAsDirectories ) )
|
||||
dialog.treatsFilePackagesAsDirectories = isOptionSet( FC_treatsFilePackagesAsDirectories );
|
||||
|
||||
// use deprecated allowedFileTypes instead of newer allowedContentTypes (since macOS 11+)
|
||||
// to support older macOS versions 10.14+ and because of some problems with allowedContentTypes:
|
||||
// https://github.com/chromium/chromium/blob/d8e0032963b7ca4728ff4117933c0feb3e479b7a/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm#L209-232
|
||||
if( nsAllowedFileTypes != NULL )
|
||||
dialog.allowedFileTypes = nsAllowedFileTypes;
|
||||
FileChooserDelegate* delegate = [FileChooserDelegate new];
|
||||
delegate.dialog = dialog;
|
||||
|
||||
if( [dialog runModal] != NSModalResponseOK )
|
||||
// initialize filter accessory view
|
||||
if( filters != NULL ) {
|
||||
[delegate initFilterAccessoryView:filters :fileTypeIndex :nsFilterFieldLabel :isOptionSet( FC_showSingleFilterField )];
|
||||
|
||||
if( open && isOptionSetOrClear( FC_accessoryViewDisclosed ) )
|
||||
((NSOpenPanel*)dialog).accessoryViewDisclosed = isOptionSet( FC_accessoryViewDisclosed );
|
||||
}
|
||||
|
||||
// show dialog
|
||||
NSModalResponse response = [dialog runModal];
|
||||
[delegate release];
|
||||
if( response != NSModalResponseOK )
|
||||
return;
|
||||
|
||||
if( open )
|
||||
|
||||
Reference in New Issue
Block a user