Reword the skin save dialog as an actual saving dialogue

This commit is contained in:
Sollace 2018-08-23 15:07:33 +02:00
parent 58b0fd2630
commit dc05d1baad
12 changed files with 120 additions and 68 deletions

View file

@ -1,8 +1,8 @@
package com.voxelmodpack.hdskins; package com.voxelmodpack.hdskins;
import com.voxelmodpack.hdskins.skins.MoreHttpResponses; import com.voxelmodpack.hdskins.skins.MoreHttpResponses;
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFile; import com.voxelmodpack.hdskins.upload.awt.IFileDialog;
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFileFolder; import com.voxelmodpack.hdskins.upload.awt.ThreadSaveFilePNG;
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG; import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
@ -39,7 +39,7 @@ public class SkinChooser {
return number != 0 && (number & number - 1) == 0; return number != 0 && (number & number - 1) == 0;
} }
private ThreadOpenFile openFileThread; private IFileDialog openFileThread;
private final SkinUploader uploader; private final SkinUploader uploader;
@ -60,29 +60,27 @@ public class SkinChooser {
} }
public void openBrowsePNG(Minecraft mc, String title) { public void openBrowsePNG(Minecraft mc, String title) {
openFileThread = new ThreadOpenFilePNG(mc, title, (fileDialog, dialogResult) -> { openFileThread = new ThreadOpenFilePNG(mc, title, (file, dialogResult) -> {
openFileThread = null; openFileThread = null;
if (dialogResult == 0) { if (dialogResult == 0) {
selectFile(fileDialog.getSelectedFile()); selectFile(file);
} }
}); });
openFileThread.start(); openFileThread.start();
} }
public void openSavePNG(Minecraft mc, String title) { public void openSavePNG(Minecraft mc, String title) {
openFileThread = new ThreadOpenFileFolder(mc, title, (fileDialog, dialogResult) -> { openFileThread = new ThreadSaveFilePNG(mc, title, mc.getSession().getUsername() + ".png", (file, dialogResult) -> {
if (dialogResult == 0) { if (dialogResult == 0) {
File out = fileDialog.getSelectedFile();
try (MoreHttpResponses response = uploader.downloadSkin().get()) { try (MoreHttpResponses response = uploader.downloadSkin().get()) {
if (response.ok()) { if (response.ok()) {
FileUtils.copyInputStreamToFile(response.getInputStream(), out); FileUtils.copyInputStreamToFile(response.getInputStream(), file);
} }
} catch (IOException | InterruptedException | ExecutionException e) { } catch (IOException | InterruptedException | ExecutionException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
openFileThread = null; openFileThread = null;
}); });
openFileThread.start(); openFileThread.start();
} }

View file

@ -129,7 +129,7 @@ public class GuiSkins extends GameGui implements ISkinUploadHandler {
addButton(btnDownload = new Button(width / 2 - 24, height / 2 + 20, 48, 20, "hdskins.options.download", sender -> { addButton(btnDownload = new Button(width / 2 - 24, height / 2 + 20, 48, 20, "hdskins.options.download", sender -> {
if (uploader.canClear()) { if (uploader.canClear()) {
chooser.openSavePNG(mc, format("hdskins.open.title")); chooser.openSavePNG(mc, format("hdskins.save.title"));
} }
})).setEnabled(uploader.canClear()).setTooltip("hdskins.options.download.title"); })).setEnabled(uploader.canClear()).setTooltip("hdskins.options.download.title");

View file

@ -0,0 +1,7 @@
package com.voxelmodpack.hdskins.upload.awt;
import java.io.File;
public interface IFileCallback {
void onDialogClosed(File file, int dialogResults);
}

View file

@ -0,0 +1,5 @@
package com.voxelmodpack.hdskins.upload.awt;
public interface IFileDialog extends Runnable {
void start();
}

View file

@ -1,18 +0,0 @@
package com.voxelmodpack.hdskins.upload.awt;
import javax.swing.JFileChooser;
/**
* Interface for objects which can receive a callback from ThreadOpenFile
*
* @author Adam Mummery-Smith
*/
@FunctionalInterface
public interface IOpenFileCallback {
/**
* Callback method called when the "open file" dialog is closed
*/
void onFileOpenDialogClosed(JFileChooser fileDialog, int dialogResult);
}

View file

@ -15,16 +15,16 @@ import com.voxelmodpack.hdskins.LiteModHDSkins;
* *
* @author Adam Mummery-Smith * @author Adam Mummery-Smith
*/ */
public abstract class ThreadOpenFile extends Thread { public abstract class ThreadOpenFile extends Thread implements IFileDialog {
protected String dialogTitle; protected String dialogTitle;
/** /**
* Delegate to call back when the dialog box is closed * Delegate to call back when the dialog box is closed
*/ */
protected final IOpenFileCallback parentScreen; protected final IFileCallback parentScreen;
protected ThreadOpenFile(Minecraft minecraft, String dialogTitle, IOpenFileCallback callback) throws IllegalStateException { protected ThreadOpenFile(Minecraft minecraft, String dialogTitle, IFileCallback callback) throws IllegalStateException {
if (minecraft.isFullScreen()) { if (minecraft.isFullScreen()) {
throw new IllegalStateException("Cannot open an awt window whilst minecraft is in full screen mode!"); throw new IllegalStateException("Cannot open an awt window whilst minecraft is in full screen mode!");
} }
@ -44,20 +44,32 @@ public abstract class ThreadOpenFile extends Thread {
} }
fileDialog.setFileFilter(getFileFilter()); fileDialog.setFileFilter(getFileFilter());
int dialogResult = fileDialog.showOpenDialog(InternalDialog.getAWTContext()); int dialogResult = showDialog(fileDialog);
File f = fileDialog.getSelectedFile(); File f = fileDialog.getSelectedFile();
if (f != null) { if (f != null) {
LiteModHDSkins.instance().lastChosenFile = f.getAbsolutePath(); LiteModHDSkins.instance().lastChosenFile = f.getAbsolutePath();
LiteModHDSkins.instance().writeConfig(); LiteModHDSkins.instance().writeConfig();
if (!f.exists() && f.getName().indexOf('.') == -1) {
f = appendMissingExtension(f);
}
} }
parentScreen.onFileOpenDialogClosed(fileDialog, dialogResult); parentScreen.onDialogClosed(f, dialogResult);
}
protected int showDialog(JFileChooser chooser) {
return chooser.showOpenDialog(InternalDialog.getAWTContext());
} }
/** /**
* Subclasses should override this to return a file filter * Subclasses should override this to return a file filter
*/ */
protected abstract FileFilter getFileFilter(); protected abstract FileFilter getFileFilter();
protected File appendMissingExtension(File file) {
return file;
}
} }

View file

@ -1,32 +0,0 @@
package com.voxelmodpack.hdskins.upload.awt;
import net.minecraft.client.Minecraft;
import javax.swing.filechooser.FileFilter;
import java.io.File;
/**
* Opens an awt "Open File" dialog that only accepts directories.
*/
public class ThreadOpenFileFolder extends ThreadOpenFile {
public ThreadOpenFileFolder(Minecraft minecraft, String dialogTitle, IOpenFileCallback callback)
throws IllegalStateException {
super(minecraft, dialogTitle, callback);
}
@Override
protected FileFilter getFileFilter() {
return new FileFilter() {
@Override
public String getDescription() {
return "Directories";
}
@Override
public boolean accept(File f) {
return f.isDirectory();
}
};
}
}

View file

@ -12,8 +12,7 @@ import java.io.File;
*/ */
public class ThreadOpenFilePNG extends ThreadOpenFile { public class ThreadOpenFilePNG extends ThreadOpenFile {
public ThreadOpenFilePNG(Minecraft minecraft, String dialogTitle, IOpenFileCallback callback) public ThreadOpenFilePNG(Minecraft minecraft, String dialogTitle, IFileCallback callback) throws IllegalStateException {
throws IllegalStateException {
super(minecraft, dialogTitle, callback); super(minecraft, dialogTitle, callback);
} }

View file

@ -0,0 +1,47 @@
package com.voxelmodpack.hdskins.upload.awt;
import net.minecraft.client.Minecraft;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import java.io.File;
/**
* Opens an awt "Save File" dialog
*/
public abstract class ThreadSaveFile extends ThreadOpenFile {
protected String filename;
protected ThreadSaveFile(Minecraft minecraft, String dialogTitle, String initialFilename, IFileCallback callback) throws IllegalStateException {
super(minecraft, dialogTitle, callback);
this.filename = initialFilename;
}
@Override
protected int showDialog(JFileChooser chooser) {
do {
chooser.setSelectedFile(new File(filename));
int result = chooser.showSaveDialog(InternalDialog.getAWTContext());
File f = chooser.getSelectedFile();
if (result == 0 && f != null && f.exists()) {
if (JOptionPane.showConfirmDialog(chooser,
"A file named \"" + f.getName() + "\" already exists. Do you want to replace it?", "Confirm",
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION) {
continue;
}
f.delete();
}
return result;
} while (true);
}
}

View file

@ -0,0 +1,34 @@
package com.voxelmodpack.hdskins.upload.awt;
import net.minecraft.client.Minecraft;
import javax.swing.filechooser.FileFilter;
import java.io.File;
public class ThreadSaveFilePNG extends ThreadSaveFile {
public ThreadSaveFilePNG(Minecraft minecraft, String dialogTitle, String filename, IFileCallback callback) {
super(minecraft, dialogTitle, filename, callback);
}
@Override
protected FileFilter getFileFilter() {
return new FileFilter() {
@Override
public String getDescription() {
return "PNG Files (*.png)";
}
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".png");
}
};
}
@Override
protected File appendMissingExtension(File file) {
return new File(file.getParentFile(), file.getName() + ".png");
}
}

View file

@ -13,6 +13,7 @@ hdskins.error.noserver=There was no valid skin server available
hdskins.error.offline=- Server Offline - hdskins.error.offline=- Server Offline -
hdskins.open.title=Choose skin hdskins.open.title=Choose skin
hdskins.save.title=Choose save location
hdskins.fetch=Fetching skin... hdskins.fetch=Fetching skin...
hdskins.failed=Uploading skin failed hdskins.failed=Uploading skin failed
hdskins.request=Sending request to server please wait... hdskins.request=Sending request to server please wait...

View file

@ -10,7 +10,6 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.voxelmodpack.hdskins.gui.EntityPlayerModel; import com.voxelmodpack.hdskins.gui.EntityPlayerModel;
import com.voxelmodpack.hdskins.gui.GuiSkins; import com.voxelmodpack.hdskins.gui.GuiSkins;
import com.voxelmodpack.hdskins.skins.SkinServer; import com.voxelmodpack.hdskins.skins.SkinServer;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents; import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;