Testing SDL-based file chooser
This commit is contained in:
@@ -142,68 +142,13 @@ public interface Platform{
|
||||
* @param title The title of the native dialog
|
||||
*/
|
||||
default void showFileChooser(boolean open, String title, String extension, Cons<Fi> cons){
|
||||
if(OS.isWindows || OS.isMac){
|
||||
if(OS.isWindows || OS.isMac || (OS.isLinux && !OS.isAndroid)){
|
||||
showNativeFileChooser(open, title, cons, extension);
|
||||
}else if(OS.isLinux && !OS.isAndroid){
|
||||
showZenity(open, title, new String[]{extension}, cons, () -> defaultFileDialog(open, title, extension, cons));
|
||||
}else{
|
||||
defaultFileDialog(open, title, extension, cons);
|
||||
}
|
||||
}
|
||||
|
||||
/** attempt to use the native file picker with zenity, or runs the fallback Runnable if the operation fails */
|
||||
static void showZenity(boolean open, String title, String[] extensions, Cons<Fi> cons, Runnable fallback){
|
||||
Threads.daemon(() -> {
|
||||
try{
|
||||
String formatted = (title.startsWith("@") ? Core.bundle.get(title.substring(1)) : title).replaceAll("\"", "'");
|
||||
|
||||
String last = FileChooser.getLastDirectory().absolutePath();
|
||||
if(!last.endsWith("/")) last += "/";
|
||||
|
||||
//zenity doesn't support filtering by extension
|
||||
Seq<String> args = Seq.with("zenity",
|
||||
"--file-selection",
|
||||
"--title=" + formatted,
|
||||
"--filename=" + last,
|
||||
"--confirm-overwrite",
|
||||
"--file-filter=" + Seq.with(extensions).toString(" ", s -> "*." + s),
|
||||
"--file-filter=All files | *" //allow anything if the user wants
|
||||
);
|
||||
|
||||
if(!open){
|
||||
args.add("--save");
|
||||
}
|
||||
|
||||
String result = OS.exec(args.toArray(String.class));
|
||||
//first line.
|
||||
if(result.length() > 1 && result.contains("\n")){
|
||||
result = result.split("\n")[0];
|
||||
}
|
||||
|
||||
//cancelled selection, ignore result
|
||||
if(result.isEmpty() || result.equals("\n")) return;
|
||||
|
||||
if(result.endsWith("\n")) result = result.substring(0, result.length() - 1);
|
||||
if(result.contains("\n")) throw new IOException("invalid input: \"" + result + "\"");
|
||||
|
||||
Fi file = Core.files.absolute(result);
|
||||
Core.app.post(() -> {
|
||||
FileChooser.setLastDirectory(file.isDirectory() ? file : file.parent());
|
||||
|
||||
if(!open){
|
||||
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extensions[0]));
|
||||
}else{
|
||||
cons.get(file);
|
||||
}
|
||||
});
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
Log.warn("zenity not found, using non-native file dialog. Consider installing `zenity` for native file dialogs.");
|
||||
Core.app.post(fallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void defaultFileDialog(boolean open, String title, String extension, Cons<Fi> cons){
|
||||
new FileChooser(title, file -> file.extEquals(extension), open, file -> {
|
||||
if(!open){
|
||||
@@ -226,10 +171,8 @@ public interface Platform{
|
||||
default void showMultiFileChooser(Cons<Fi> cons, String... extensions){
|
||||
if(mobile){
|
||||
showFileChooser(true, extensions[0], cons);
|
||||
}else if(OS.isWindows || OS.isMac){
|
||||
}else if(OS.isWindows || OS.isMac || (OS.isLinux && !OS.isAndroid)){
|
||||
showNativeFileChooser(true, "@open", cons, extensions);
|
||||
}else if(OS.isLinux && !OS.isAndroid){
|
||||
showZenity(true, "@open", extensions, cons, () -> defaultMultiFileChooser(cons, extensions));
|
||||
}else{
|
||||
defaultMultiFileChooser(cons, extensions);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.backend.sdl.*;
|
||||
import arc.discord.*;
|
||||
import arc.discord.DiscordRPC.*;
|
||||
import arc.files.*;
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.profiling.*;
|
||||
import arc.struct.*;
|
||||
@@ -14,7 +15,7 @@ import arc.util.Log.*;
|
||||
import arc.util.serialization.*;
|
||||
import com.codedisaster.steamworks.*;
|
||||
import mindustry.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.core.Version;
|
||||
import mindustry.desktop.steam.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -24,7 +25,10 @@ import mindustry.net.*;
|
||||
import mindustry.net.Net.*;
|
||||
import mindustry.service.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.dialogs.*;
|
||||
import org.lwjgl.*;
|
||||
import org.lwjgl.sdl.*;
|
||||
import org.lwjgl.system.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@@ -292,6 +296,56 @@ public class DesktopLauncher extends ClientLauncher{
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNativeFileChooser(boolean open, String title, Cons<Fi> cons, String... shownExtensions){
|
||||
String[] ext = shownExtensions == null || shownExtensions.length == 0 ? new String[]{""} : shownExtensions;
|
||||
|
||||
SDL_DialogFileFilter.Buffer filters = SDL_DialogFileFilter.calloc(ext.length);
|
||||
try(MemoryStack stack = MemoryStack.stackPush()){
|
||||
for(int i = 0; i < ext.length; i++){
|
||||
String extName = ext[i];
|
||||
|
||||
var filter = SDL_DialogFileFilter.calloc(stack)
|
||||
.name(MemoryUtil.memUTF8(extName.isEmpty() ? "All Files" : "." + extName + " files"))
|
||||
.pattern(MemoryUtil.memUTF8(extName.isEmpty() ? "*" : extName));
|
||||
|
||||
filters.put(i, filter);
|
||||
}
|
||||
}
|
||||
SDL_DialogFileCallbackI callback = (userData, files, filter) -> {
|
||||
if(files != 0){
|
||||
PointerBuffer pointerBuffer = MemoryUtil.memPointerBuffer(files, 1);
|
||||
long firstFile = pointerBuffer.get();
|
||||
if(firstFile != 0){
|
||||
String result = MemoryUtil.memUTF8(firstFile);
|
||||
|
||||
if(result.isEmpty() || result.equals("\n")) return;
|
||||
if(result.endsWith("\n")) result = result.substring(0, result.length() - 1);
|
||||
if(result.contains("\n")) return;
|
||||
|
||||
Fi file = Core.files.absolute(result);
|
||||
Core.app.post(() -> {
|
||||
FileChooser.setLastDirectory(file.isDirectory() ? file : file.parent());
|
||||
|
||||
if(!open){
|
||||
cons.get(file.parent().child(file.nameWithoutExtension() + "." + ext[0]));
|
||||
}else{
|
||||
cons.get(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(open){
|
||||
SDLDialog.SDL_ShowOpenFileDialog(callback, 0, ((SdlApplication)Core.app).getWindow(), filters, FileChooser.getLastDirectory().absolutePath(), false);
|
||||
}else{
|
||||
SDLDialog.SDL_ShowSaveFileDialog(callback, 0, ((SdlApplication)Core.app).getWindow(), filters, FileChooser.getLastDirectory().absolutePath());
|
||||
}
|
||||
|
||||
filters.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Seq<Fi> getWorkshopContent(Class<? extends Publishable> type){
|
||||
return !steam ? super.getWorkshopContent(type) : SVars.workshop.getWorkshopFiles(type);
|
||||
|
||||
Reference in New Issue
Block a user