* refactor NSOpenPanel code in the hopes of fixing random deadlock issues when NSOpenPanel is shown (somehow only affects a very small number of users)
This commit is contained in:
parent
cdd5d668b8
commit
82a14c55c6
|
@ -16,13 +16,11 @@ import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.prefs.BackingStoreException;
|
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
|
|
||||||
import net.filebot.mac.MacAppUtilities;
|
import net.filebot.mac.MacAppUtilities;
|
||||||
import net.filebot.mac.NativeFileDialog;
|
|
||||||
import net.filebot.util.FileUtilities.ExtensionFileFilter;
|
import net.filebot.util.FileUtilities.ExtensionFileFilter;
|
||||||
|
|
||||||
public class UserFiles {
|
public class UserFiles {
|
||||||
|
@ -211,28 +209,13 @@ public class UserFiles {
|
||||||
// NSOpenPanel causes deadlocks on some machines
|
// NSOpenPanel causes deadlocks on some machines
|
||||||
Preferences persistence = Preferences.userNodeForPackage(UserFiles.class);
|
Preferences persistence = Preferences.userNodeForPackage(UserFiles.class);
|
||||||
if (!persistence.getBoolean(KEY_NSOPENPANEL_BROKEN, false)) {
|
if (!persistence.getBoolean(KEY_NSOPENPANEL_BROKEN, false)) {
|
||||||
// assume that NSOpenPanel may freeze the application until it is killed, and make sure to not use NSOpenPanel on subsequent runs
|
|
||||||
try {
|
try {
|
||||||
|
// assume that NSOpenPanel may freeze the application until it is killed, and make sure to not use NSOpenPanel on subsequent runs
|
||||||
persistence.putBoolean(KEY_NSOPENPANEL_BROKEN, true);
|
persistence.putBoolean(KEY_NSOPENPANEL_BROKEN, true);
|
||||||
persistence.flush();
|
persistence.flush();
|
||||||
} catch (BackingStoreException e) {
|
|
||||||
Logger.getLogger(UserFiles.class.getName()).log(Level.WARNING, e.toString(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
// call native NSOpenPanel openPanel via Objective-C bridge
|
||||||
NativeFileDialog nsOpenPanel = new NativeFileDialog(title, FileDialog.LOAD);
|
return MacAppUtilities.NSOpenPanel_openPanel_runModal(title, true, true, true, filter.acceptAny() ? filter.extensions() : null);
|
||||||
nsOpenPanel.setMultipleMode(true);
|
|
||||||
nsOpenPanel.setCanChooseDirectories(true);
|
|
||||||
nsOpenPanel.setCanChooseFiles(true);
|
|
||||||
if (!filter.acceptAny()) {
|
|
||||||
nsOpenPanel.setAllowedFileTypes(asList(filter.extensions()));
|
|
||||||
}
|
|
||||||
nsOpenPanel.setVisible(true);
|
|
||||||
if (!nsOpenPanel.isCancelled()) {
|
|
||||||
return asList(nsOpenPanel.getFiles());
|
|
||||||
} else {
|
|
||||||
return emptyList();
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Logger.getLogger(UserFiles.class.getName()).log(Level.WARNING, e.toString());
|
Logger.getLogger(UserFiles.class.getName()).log(Level.WARNING, e.toString());
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
package net.filebot.mac;
|
package net.filebot.mac;
|
||||||
|
|
||||||
|
import static ca.weblite.objc.util.CocoaUtils.*;
|
||||||
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
import ca.weblite.objc.Client;
|
import ca.weblite.objc.Client;
|
||||||
|
import ca.weblite.objc.Proxy;
|
||||||
|
|
||||||
public class MacAppUtilities {
|
public class MacAppUtilities {
|
||||||
|
|
||||||
|
@ -34,6 +39,40 @@ public class MacAppUtilities {
|
||||||
return objc().sendProxy("NSURL", "URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:", NSData_initWithBase64Encoding(text), 1024, null, false, null).send("startAccessingSecurityScopedResource");
|
return objc().sendProxy("NSURL", "URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:", NSData_initWithBase64Encoding(text), 1024, null, false, null).send("startAccessingSecurityScopedResource");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<File> NSOpenPanel_openPanel_runModal(String title, boolean multipleMode, boolean canChooseDirectories, boolean canChooseFiles, String[] allowedFileTypes) {
|
||||||
|
List<File> result = new ArrayList<File>();
|
||||||
|
dispatch_sync(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Proxy peer = objc().sendProxy("NSOpenPanel", "openPanel");
|
||||||
|
peer.send("setTitle:", title);
|
||||||
|
peer.send("setAllowsMultipleSelection:", multipleMode ? 1 : 0);
|
||||||
|
peer.send("setCanChooseDirectories:", canChooseDirectories ? 1 : 0);
|
||||||
|
peer.send("setCanChooseFiles:", canChooseFiles ? 1 : 0);
|
||||||
|
|
||||||
|
if (allowedFileTypes != null) {
|
||||||
|
Proxy mutableArray = objc().sendProxy("NSMutableArray", "arrayWithCapacity:", allowedFileTypes.length);
|
||||||
|
for (String type : allowedFileTypes) {
|
||||||
|
mutableArray.send("addObject:", type);
|
||||||
|
}
|
||||||
|
peer.send("setAllowedFileTypes:", mutableArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer.sendInt("runModal") != 0) {
|
||||||
|
Proxy nsArray = peer.getProxy("URLs");
|
||||||
|
int size = nsArray.sendInt("count");
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
Proxy url = nsArray.sendProxy("objectAtIndex:", i);
|
||||||
|
String path = url.sendString("path");
|
||||||
|
result.add(new File(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setWindowCanFullScreen(Window window) {
|
public static void setWindowCanFullScreen(Window window) {
|
||||||
try {
|
try {
|
||||||
Class<?> fullScreenUtilities = Class.forName("com.apple.eawt.FullScreenUtilities");
|
Class<?> fullScreenUtilities = Class.forName("com.apple.eawt.FullScreenUtilities");
|
||||||
|
|
|
@ -1,580 +0,0 @@
|
||||||
package net.filebot.mac;
|
|
||||||
|
|
||||||
import static ca.weblite.objc.RuntimeUtils.*;
|
|
||||||
import static ca.weblite.objc.util.CocoaUtils.*;
|
|
||||||
|
|
||||||
import java.awt.FileDialog;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import ca.weblite.objc.NSObject;
|
|
||||||
import ca.weblite.objc.Proxy;
|
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper around NSSavePanel and NSOpenPanel with some methods similar to java.awt.FileDialog.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This class includes wrappers for most settings of both NSSavePanel and NSOpen panel so that you have full flexibility (e.g. select directories only, files only, force a certain extension, allow user to add folders, show hidden files, etc...
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <h3>Example Save Panel</h3> <code><pre>
|
|
||||||
* NativeFileDialog dlg = new NativeFileDialog("Save as...", FileDialog.SAVE);
|
|
||||||
dlg.setMessage("Will save only as .txt file");
|
|
||||||
dlg.setExtensionHidden(true);
|
|
||||||
dlg.setAllowedFileTypes(Arrays.asList("txt"));
|
|
||||||
dlg.setVisible(true); // this is modal
|
|
||||||
|
|
||||||
String f = dlg.getFile();
|
|
||||||
if ( f == null ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
File file = new File(f);
|
|
||||||
saveFile(file);
|
|
||||||
* </pre></code>
|
|
||||||
*
|
|
||||||
* <h3>Example Open Panel</h3>
|
|
||||||
*
|
|
||||||
* <code><pre>
|
|
||||||
* NativeFileDialog dlg = new NativeFileDialog("Select file to open", FileDialog.LOAD);
|
|
||||||
dlg.setVisible(true); // this is modal.
|
|
||||||
String f = dlg.getFile();
|
|
||||||
if ( f != null ){
|
|
||||||
openFile(new File(f));
|
|
||||||
}
|
|
||||||
* </pre></code>
|
|
||||||
*
|
|
||||||
* @author shannah
|
|
||||||
* @see <a href="https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html">NSSavePanel Class Reference</a>
|
|
||||||
* @see <a href="https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nsopenpanel_Class/Reference/Reference.html">NSOpenPanel Class Reference</a>
|
|
||||||
* @see <a href="http://docs.oracle.com/javase/7/docs/api/java/awt/FileDialog.html">java.awt.FileDialog API docs</a>
|
|
||||||
*/
|
|
||||||
public class NativeFileDialog extends NSObject {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reference to the Obj-C NSOpenPanel or NSSavePanel class.
|
|
||||||
*/
|
|
||||||
private Proxy peer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Either FileDialog.LOAD or FileDialog.SAVE
|
|
||||||
*/
|
|
||||||
private int mode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new file dialog with the specified title and mode.
|
|
||||||
*
|
|
||||||
* @param title
|
|
||||||
* The title for the dialog.
|
|
||||||
* @param mode
|
|
||||||
* Whether to be an open panel or save panel. Either java.awt.FileDialog.SAVE or java.awt.FileDialog.LOAD
|
|
||||||
*/
|
|
||||||
public NativeFileDialog(final String title, final int mode) {
|
|
||||||
super("NSObject");
|
|
||||||
this.mode = mode;
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mode == FileDialog.LOAD) {
|
|
||||||
peer = getClient().sendProxy("NSOpenPanel", "openPanel");
|
|
||||||
} else {
|
|
||||||
peer = getClient().sendProxy("NSSavePanel", "savePanel");
|
|
||||||
}
|
|
||||||
peer.send("setTitle:", title);
|
|
||||||
peer.send("retain");
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a given selector with a string value on the main thread.
|
|
||||||
*
|
|
||||||
* @param selector
|
|
||||||
* An objective-c selector on the NSSavePanel object. e.g. "setTitle:"
|
|
||||||
* @param value
|
|
||||||
* The value to set the selector.
|
|
||||||
*/
|
|
||||||
private void set(final String selector, final String value) {
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (peer.getPeer().equals(Pointer.NULL)) {
|
|
||||||
|
|
||||||
throw new RuntimeException("The peer is null");
|
|
||||||
}
|
|
||||||
peer.send(sel(selector), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a given selector with an int value on the main thread.
|
|
||||||
*
|
|
||||||
* @param selector
|
|
||||||
* An objective-c selector on the NSSavePanel object. e.g. "setShowsHiddenFiles:"
|
|
||||||
* @param value
|
|
||||||
* The int value to set.
|
|
||||||
*/
|
|
||||||
private void set(final String selector, final int value) {
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
peer.send(selector, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the result of a selector on the main thread for the NSSavePanel object.
|
|
||||||
*
|
|
||||||
* @param selector
|
|
||||||
* The selector to be run. e.g. "title".
|
|
||||||
* @return The result of calling the given selector on the NSSavePanel object.
|
|
||||||
*/
|
|
||||||
private String getString(final String selector) {
|
|
||||||
final String[] out = new String[1];
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
out[0] = peer.sendString(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return out[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the result of running a selector on the NSSavePanel on the main thread.
|
|
||||||
*
|
|
||||||
* @param selector
|
|
||||||
* The selector to be run. E.g. "showsHiddenFiles"
|
|
||||||
* @return The int result.
|
|
||||||
*/
|
|
||||||
private int getI(final String selector) {
|
|
||||||
final int[] out = new int[1];
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
out[0] = peer.sendInt(sel(selector));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return out[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets title of the dialog.
|
|
||||||
*
|
|
||||||
* @param title
|
|
||||||
* The title.
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
*/
|
|
||||||
public void setTitle(String title) {
|
|
||||||
set("setTitle:", title);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the title of the dialog.
|
|
||||||
*
|
|
||||||
* @return The title
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
*/
|
|
||||||
public String getTitle() {
|
|
||||||
return getString("title");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param prompt
|
|
||||||
*/
|
|
||||||
public void setPrompt(String prompt) {
|
|
||||||
set("setPrompt:", prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param label
|
|
||||||
*/
|
|
||||||
public void setNameFieldLabel(String label) {
|
|
||||||
set("setNameFieldLabel:", label);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getNameFieldLabel() {
|
|
||||||
return getString("nameFieldLabel");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param message
|
|
||||||
*/
|
|
||||||
public void setMessage(String message) {
|
|
||||||
set("setMessage:", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getMessage() {
|
|
||||||
return getString("message");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getPrompt() {
|
|
||||||
return getString("prompt");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean canCreateDirectories() {
|
|
||||||
return getI("canCreateDirectories") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param can
|
|
||||||
*/
|
|
||||||
public void setCanCreateDirectories(boolean can) {
|
|
||||||
set("setCanCreateDirectories:", can ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean showsHiddenFiles() {
|
|
||||||
return getI("showsHiddenFiles") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param shows
|
|
||||||
*/
|
|
||||||
public void setShowsHiddenFiles(boolean shows) {
|
|
||||||
set("setShowsHiddenFiles:", shows ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isExtensionHidden() {
|
|
||||||
return getI("isExtensionHidden") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param hidden
|
|
||||||
*/
|
|
||||||
public void setExtensionHidden(boolean hidden) {
|
|
||||||
set("setExtensionHidden:", hidden ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean canSelectHiddenExtension() {
|
|
||||||
return getI("canSelectHiddenExtension") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param sel
|
|
||||||
*/
|
|
||||||
public void setCanSelectHiddenExtension(boolean sel) {
|
|
||||||
set("setCanSelectHiddenExtension:", sel ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param val
|
|
||||||
*/
|
|
||||||
public void setNameFieldStringValue(String val) {
|
|
||||||
set("setNameFieldStringValue:", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public List<String> getAllowedFileTypes() {
|
|
||||||
final List<String> out = new ArrayList<String>();
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Proxy types = peer.sendProxy("allowedFileTypes");
|
|
||||||
int size = types.getInt("count");
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
String nex = types.sendString("objectAtIndex:", i);
|
|
||||||
out.add(nex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param types
|
|
||||||
*/
|
|
||||||
public void setAllowedFileTypes(final List<String> types) {
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Proxy mutableArray = getClient().sendProxy("NSMutableArray", "arrayWithCapacity:", types.size());
|
|
||||||
|
|
||||||
for (String type : types) {
|
|
||||||
|
|
||||||
mutableArray.send("addObject:", type);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
peer.send("setAllowedFileTypes:", mutableArray);
|
|
||||||
|
|
||||||
// mutableArray.send("release");
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean allowsOtherFileTypes() {
|
|
||||||
return getI("allowsOtherFileTypes") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param allowed
|
|
||||||
*/
|
|
||||||
public void setAllowsOtherFileTypes(boolean allowed) {
|
|
||||||
set("setAllowsOtherFileTypes:", allowed ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean getTreatsFilePackagesAsDirectories() {
|
|
||||||
return getI("treatsFilePackagesAsDirectories") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nssavepanel_Class/Reference/Reference.html
|
|
||||||
* @param treat
|
|
||||||
*/
|
|
||||||
public void setTreatsFilePackagesAsDirectories(boolean treat) {
|
|
||||||
set("setTreatsFilePackagesAsDirectories:", treat ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the path to the directory that was selected.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getDirectory() {
|
|
||||||
final String[] out = new String[1];
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Proxy dirUrl = peer.sendProxy("directoryURL");
|
|
||||||
if (dirUrl.getPeer().equals(Pointer.NULL)) {
|
|
||||||
out[0] = null;
|
|
||||||
} else {
|
|
||||||
out[0] = dirUrl.sendString("path");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return out[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path to the file that was selected.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getFile() {
|
|
||||||
final String[] out = new String[1];
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Proxy fileUrl = peer.sendProxy("URL");
|
|
||||||
if (fileUrl == null || fileUrl.getPeer().equals(Pointer.NULL)) {
|
|
||||||
out[0] = null;
|
|
||||||
} else {
|
|
||||||
out[0] = fileUrl.sendString("path");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return out[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of files that were selected by the user.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public File[] getFiles() {
|
|
||||||
final List<File> out = new ArrayList<File>();
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mode == FileDialog.LOAD) {
|
|
||||||
Proxy nsArray = peer.getProxy("URLs");
|
|
||||||
if (!nsArray.getPeer().equals(Pointer.NULL)) {
|
|
||||||
int size = nsArray.sendInt("count");
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
Proxy url = nsArray.sendProxy("objectAtIndex:", i);
|
|
||||||
String path = url.sendString("path");
|
|
||||||
out.add(new File(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return out.toArray(new File[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the mode of this dialog.
|
|
||||||
*
|
|
||||||
* @return either FileDialog.LOAD or FileDialog.SAVE
|
|
||||||
*/
|
|
||||||
public int getMode() {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the dialog allows multiple selection.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isMultipleMode() {
|
|
||||||
return getI("allowsMultipleSelection") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the dialog allows the user to select multiple files or not.
|
|
||||||
*
|
|
||||||
* @param enable
|
|
||||||
*/
|
|
||||||
public void setMultipleMode(boolean enable) {
|
|
||||||
set("setAllowsMultipleSelection:", enable ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the user can select files in this dialog.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean canChooseFiles() {
|
|
||||||
return getI("canChooseFiles") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the user can select files in this dialog.
|
|
||||||
*
|
|
||||||
* @param can
|
|
||||||
*/
|
|
||||||
public void setCanChooseFiles(boolean can) {
|
|
||||||
set("setCanChooseFiles:", can ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getCanChooseDirectories() {
|
|
||||||
return getI("canChooseDirectories") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCanChooseDirectories(boolean can) {
|
|
||||||
set("setCanChooseDirectories:", can ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getResolvesAliases() {
|
|
||||||
return getI("resolvesAliases") != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResolvesAliases(boolean resolves) {
|
|
||||||
set("setResolvesAliases:", resolves ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the directory that the dialog displays.
|
|
||||||
*
|
|
||||||
* @param dir
|
|
||||||
*/
|
|
||||||
public void setDirectory(final String dir) {
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Proxy url = getClient().sendProxy("NSURL", "fileURLWithPath:isDirectory:", dir, 1);
|
|
||||||
peer.send("setDirectoryURL:", url.getPeer());
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVisible(boolean visible) {
|
|
||||||
dispatch_sync(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int result = peer.sendInt("runModal");
|
|
||||||
nsFileHandlingButton.set(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getResult() {
|
|
||||||
return nsFileHandlingButton.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return nsFileHandlingButton.get() == NSFileHandlingPanelCancelButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicInteger nsFileHandlingButton = new AtomicInteger(NSFileHandlingPanelCancelButton);
|
|
||||||
|
|
||||||
public static final int NSFileHandlingPanelOKButton = 1;
|
|
||||||
public static final int NSFileHandlingPanelCancelButton = 0;
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue