From 593a518fab5666c7608f3650a4b952eb397847f6 Mon Sep 17 00:00:00 2001 From: johni0702 Date: Mon, 12 Oct 2015 22:07:31 +0200 Subject: [PATCH] Rewrite GuiReplayViewer Move rename replay gui as popup into replay viewer --- .../com/replaymod/replay/ReplayModReplay.java | 4 + .../replay/gui/screen/GuiRenameReplay.java | 98 --- .../replay/gui/screen/GuiReplayViewer.java | 627 +++++++++--------- .../replay/gui/screen/ReplayList.java | 29 - .../replaymod/replay/handler/GuiHandler.java | 2 +- .../replaymod/gui/online/GuiUploadFile.java | 8 +- .../assets/replaymod/lang/en_US.lang | 4 +- 7 files changed, 332 insertions(+), 440 deletions(-) delete mode 100755 src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java delete mode 100755 src/main/java/com/replaymod/replay/gui/screen/ReplayList.java diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index 8f5f4167..468d4892 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -101,4 +101,8 @@ public class ReplayModReplay { public ReplayMod getCore() { return core; } + + public Logger getLogger() { + return logger; + } } diff --git a/src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java b/src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java deleted file mode 100755 index f5c30851..00000000 --- a/src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.replaymod.replay.gui.screen; - -import de.johni0702.minecraft.gui.container.AbstractGuiScreen; -import de.johni0702.minecraft.gui.container.GuiPanel; -import de.johni0702.minecraft.gui.element.GuiButton; -import de.johni0702.minecraft.gui.element.GuiLabel; -import de.johni0702.minecraft.gui.element.GuiTextField; -import de.johni0702.minecraft.gui.layout.CustomLayout; -import de.johni0702.minecraft.gui.layout.VerticalLayout; -import eu.crushedpixel.replaymod.utils.ReplayFileIO; -import net.minecraft.client.gui.GuiErrorScreen; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.resources.I18n; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.lwjgl.util.Color; - -import java.io.File; -import java.io.IOException; - -public class GuiRenameReplay extends AbstractGuiScreen { - public final GuiScreen parent; - public final File file; - - public final GuiLabel nameLabel = new GuiLabel().setI18nText("replaymod.gui.viewer.rename.name") - .setColor(new Color(0xa0, 0xa0, 0xa0)); - public final GuiTextField nameField = new GuiTextField().setSize(200, 20).setFocused(true).onEnter(new Runnable() { - @Override - public void run() { - renameButton.onClick(); - } - }).onTextChanged(new Runnable() { - @Override - public void run() { - renameButton.setEnabled(!nameField.getText().isEmpty()); - } - }); - - public final GuiButton renameButton = new GuiButton().setSize(200, 20).setI18nLabel("replaymod.gui.rename") - .onClick(new Runnable() { - @Override - public void run() { - // Sanitize their input - String name = nameField.getText().trim().replace("[^a-zA-Z0-9\\.\\- ]", "_"); - // This file is what they want - File targetFile = new File(file.getParentFile(), name + ".mcpr"); - // But if it's already used, this is what they get - File renamed = ReplayFileIO.getNextFreeFile(targetFile); - try { - // Finally, try to move it - FileUtils.moveFile(file, renamed); - } catch (IOException e) { - // We failed (might also be their OS) - e.printStackTrace(); - getMinecraft().displayGuiScreen(new GuiErrorScreen( - I18n.format("replaymod.gui.viewer.delete.failed1"), - I18n.format("replaymod.gui.viewer.delete.failed2") - )); - return; - } - getMinecraft().displayGuiScreen(parent); - } - }); - public final GuiButton cancelButton = new GuiButton().setSize(200, 20).setI18nLabel("replaymod.gui.cancel") - .onClick(new Runnable() { - @Override - public void run() { - getMinecraft().displayGuiScreen(parent); - } - }); - - public final GuiPanel inputPanel = new GuiPanel(this).setLayout(new VerticalLayout().setSpacing(5)) - .addElements(null, nameLabel, nameField); - public final GuiPanel buttonPanel = new GuiPanel(this).setLayout(new VerticalLayout().setSpacing(5)) - .addElements(null, renameButton, cancelButton); - - public GuiRenameReplay(GuiScreen parent, File file) { - this.parent = parent; - this.file = file; - - nameField.setText(FilenameUtils.getBaseName(file.getName())); - - setLayout(new CustomLayout() { - @Override - protected void layout(GuiRenameReplay container, int width, int height) { - pos(inputPanel, width / 2 - width(inputPanel) / 2, 60); - pos(buttonPanel, width / 2 - width(buttonPanel) / 2, height / 4 + 100); - } - }); - - setTitle(new GuiLabel().setI18nText("replaymod.gui.viewer.rename.title")); - } - - @Override - protected GuiRenameReplay getThis() { - return this; - } -} diff --git a/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java index e1372e34..5a36b17e 100755 --- a/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java +++ b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java @@ -1,360 +1,377 @@ package com.replaymod.replay.gui.screen; import com.google.common.base.Optional; -import com.mojang.realmsclient.util.Pair; -import com.replaymod.core.ReplayMod; +import com.google.common.base.Supplier; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.mojang.realmsclient.gui.ChatFormatting; import com.replaymod.core.gui.GuiReplaySettings; import com.replaymod.replay.ReplayModReplay; +import de.johni0702.minecraft.gui.container.AbstractGuiContainer; +import de.johni0702.minecraft.gui.container.AbstractGuiScreen; +import de.johni0702.minecraft.gui.container.GuiContainer; +import de.johni0702.minecraft.gui.container.GuiPanel; +import de.johni0702.minecraft.gui.element.*; +import de.johni0702.minecraft.gui.element.advanced.GuiResourceLoadingList; +import de.johni0702.minecraft.gui.layout.CustomLayout; +import de.johni0702.minecraft.gui.layout.GridLayout; +import de.johni0702.minecraft.gui.layout.HorizontalLayout; +import de.johni0702.minecraft.gui.layout.VerticalLayout; +import de.johni0702.minecraft.gui.popup.GuiYesNoPopup; +import de.johni0702.minecraft.gui.utils.Colors; +import de.johni0702.minecraft.gui.utils.Consumer; import de.johni0702.replaystudio.replay.ReplayFile; import de.johni0702.replaystudio.replay.ReplayMetaData; import de.johni0702.replaystudio.replay.ZipReplayFile; import de.johni0702.replaystudio.studio.ReplayStudio; -import eu.crushedpixel.replaymod.api.replay.holders.FileInfo; -import eu.crushedpixel.replaymod.gui.elements.GuiLoadingListEntry; -import eu.crushedpixel.replaymod.gui.elements.GuiReplayListEntry; -import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; -import eu.crushedpixel.replaymod.gui.online.GuiUploadFile; import eu.crushedpixel.replaymod.registry.ResourceHelper; -import eu.crushedpixel.replaymod.utils.ImageUtils; +import eu.crushedpixel.replaymod.utils.DurationUtils; import eu.crushedpixel.replaymod.utils.ReplayFileIO; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; +import net.minecraft.client.gui.GuiErrorScreen; import net.minecraft.client.resources.I18n; import net.minecraft.util.Util; import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.helpers.Strings; import org.lwjgl.Sys; -import org.lwjgl.input.Keyboard; +import org.lwjgl.util.Dimension; +import org.lwjgl.util.ReadableDimension; -import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; +import java.io.FileFilter; import java.io.IOException; -import java.util.*; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.text.SimpleDateFormat; +import java.util.Date; -public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback { - - private static final int LOAD_BUTTON_ID = 9001; - private static final int UPLOAD_BUTTON_ID = 9002; - private static final int FOLDER_BUTTON_ID = 9003; - private static final int RENAME_BUTTON_ID = 9004; - private static final int DELETE_BUTTON_ID = 9005; - private static final int SETTINGS_BUTTON_ID = 9006; - private static final int CANCEL_BUTTON_ID = 9007; +public class GuiReplayViewer extends AbstractGuiScreen { private final ReplayModReplay mod; - private boolean initialized; - private GuiReplayListExtended replayGuiList; - private List, File>> replayFileList = new ArrayList, File>>(); - private GuiButton loadButton; - private GuiButton uploadButton; - private GuiButton renameButton; - private GuiButton deleteButton; - private boolean delete_file = false; - - private Queue loadedReplaysQueue = new ConcurrentLinkedQueue(); - - private Thread fileReloader; - - public GuiReplayViewer(ReplayModReplay mod) { - this.mod = mod; - } - - private class FileReloaderThread extends Thread { - private final GuiLoadingListEntry loadingListEntry = new GuiLoadingListEntry(); - - @Override - public synchronized void start() { - replayFileList = new ArrayList, File>>(); - replayGuiList.clearEntries(); - replayGuiList.addEntry(loadingListEntry); - super.start(); - } + public final GuiResourceLoadingList list = new GuiResourceLoadingList(this).onSelectionChanged(new Runnable() { @Override public void run() { - for(final File file : ReplayFileIO.getAllReplayFiles()) { - if(interrupted()) break; - try { - ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file); - final ReplayMetaData metaData = replayFile.getMetaData(); - Optional thumb = replayFile.getThumb(); + replayButtonPanel.forEach(IGuiButton.class).setEnabled(list.getSelected() != null); + } + }).onLoad(new Consumer>> () { + @Override + public void consume(Consumer> obj) { + try { + File folder = mod.getCore().getReplayFolder(); + for (final File file : folder.listFiles((FileFilter) new SuffixFileFilter(".mcpr", IOCase.INSENSITIVE))) { + if (Thread.interrupted()) break; + try (ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file)) { - replayFile.close(); - - File tmp = null; - if(thumb.isPresent()) { - BufferedImage img = ImageUtils.scaleImage(thumb.get(), new Dimension(1280, 720)); - tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath())+"_THUMBNAIL", "jpg"); - tmp.deleteOnExit(); - - ImageIO.write(img, "jpg", tmp); - } - - final File thumbFile = tmp; - loadedReplaysQueue.offer(new Runnable() { - @Override - public void run() { - addEntry(file, metaData, thumbFile); + Optional thumb = replayFile.getThumb(); + // Make sure that to int[] conversion doesn't have to occur in main thread + final BufferedImage theThumb; + if (thumb.isPresent()) { + BufferedImage buf = thumb.get(); + // This is the same way minecraft calls this method, we cache the result and hand + // minecraft a BufferedImage with way simpler logic using the precomputed values + final int[] theIntArray = buf.getRGB(0, 0, buf.getWidth(), buf.getHeight(), null, 0, buf.getWidth()); + theThumb = new BufferedImage(buf.getWidth(), buf.getHeight(), BufferedImage.TYPE_INT_ARGB) { + @Override + public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) { + System.arraycopy(theIntArray, 0, rgbArray, 0, theIntArray.length); + return null; // Minecraft doesn't use the return value + } + }; + } else { + theThumb = null; } - }); - } catch(Exception e) { - FMLLog.getLogger().error("Could not load Replay File "+file.getName(), e); - } - } + final ReplayMetaData metaData = replayFile.getMetaData(); - loadedReplaysQueue.offer(new Runnable() { + obj.consume(new Supplier() { + @Override + public GuiReplayEntry get() { + return new GuiReplayEntry(file, metaData, theThumb); + } + }); + } catch (Exception e) { + FMLLog.getLogger().error("Could not load Replay File " + file.getName(), e); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }).setDrawShadow(true).setDrawSlider(true); + + public final GuiButton loadButton = new GuiButton().onClick(new Runnable() { + @Override + public void run() { + try { + mod.startReplay(list.getSelected().file); + } catch (IOException e) { + e.printStackTrace(); + } + } + }).setSize(73, 20).setI18nLabel("replaymod.gui.load").setDisabled(); + + public final GuiButton folderButton = new GuiButton().onClick(new Runnable() { + @Override + public void run() { + try { + File folder = mod.getCore().getReplayFolder(); + String path = folder.getAbsolutePath(); + + // First try OS specific methods + try { + switch (Util.getOSType()) { + case WINDOWS: + Runtime.getRuntime().exec(String.format("cmd.exe /C start \"Open file\" \"%s\"", path)); + return; + case OSX: + Runtime.getRuntime().exec(new String[]{"/usr/bin/open", path}); + return; + } + } catch (IOException e) { + LogManager.getLogger().error("Cannot open file", e); + } + + // Otherwise try to java way + try { + Desktop.getDesktop().browse(folder.toURI()); + } catch (Throwable throwable) { + // And if all fails, lwjgl + Sys.openURL("file://" + path); + } + } catch (IOException e) { + mod.getLogger().error("Cannot open file", e); + } + } + }).setSize(150, 20).setI18nLabel("replaymod.gui.viewer.replayfolder"); + + public final GuiButton renameButton = new GuiButton().onClick(new Runnable() { + @Override + public void run() { + final File file = list.getSelected().file; + String name = FilenameUtils.getBaseName(file.getName()); + final GuiTextField nameField = new GuiTextField().setSize(200, 20).setFocused(true).setText(name); + final GuiYesNoPopup popup = GuiYesNoPopup.open(GuiReplayViewer.this, + new GuiLabel().setI18nText("replaymod.gui.viewer.rename.name").setColor(Colors.BLACK), + nameField + ).setYesI18nLabel("replaymod.gui.rename").setNoI18nLabel("replaymod.gui.cancel"); + ((VerticalLayout) popup.getInfo().getLayout()).setSpacing(7); + nameField.onEnter(new Runnable() { @Override public void run() { - replayGuiList.removeEntry(loadingListEntry); + if (popup.getYesButton().isEnabled()) { + popup.getYesButton().onClick(); + } + } + }).onTextChanged(new Runnable() { + @Override + public void run() { + popup.getYesButton().setEnabled(!nameField.getText().isEmpty()); + } + }); + Futures.addCallback(popup.getFuture(), new FutureCallback() { + @Override + public void onSuccess(Boolean delete) { + if (delete) { + // Sanitize their input + String name = nameField.getText().trim().replace("[^a-zA-Z0-9\\.\\- ]", "_"); + // This file is what they want + File targetFile = new File(file.getParentFile(), name + ".mcpr"); + // But if it's already used, this is what they get + File renamed = ReplayFileIO.getNextFreeFile(targetFile); + try { + // Finally, try to move it + FileUtils.moveFile(file, renamed); + } catch (IOException e) { + // We failed (might also be their OS) + e.printStackTrace(); + getMinecraft().displayGuiScreen(new GuiErrorScreen( + I18n.format("replaymod.gui.viewer.delete.failed1"), + I18n.format("replaymod.gui.viewer.delete.failed2") + )); + return; + } + list.load(); + } + } + + @Override + public void onFailure(Throwable t) { + t.printStackTrace(); } }); } - } - - public static GuiYesNo getYesNoGui(GuiYesNoCallback p_152129_0_, String file, int p_152129_2_) { - String s1 = I18n.format("replaymod.gui.viewer.delete.linea"); - String s2 = "\'" + file + "\' " + I18n.format("replaymod.gui.viewer.delete.lineb"); - String s3 = I18n.format("replaymod.gui.delete"); - String s4 = I18n.format("replaymod.gui.cancel"); - return new GuiYesNo(p_152129_0_, s1, s2, s3, s4, p_152129_2_); - } - - @Override - public void onGuiClosed() { - ResourceHelper.freeAllResources(); - super.onGuiClosed(); - } - - @Override - @SuppressWarnings("deprecation") - public void initGui() { - Keyboard.enableRepeatEvents(true); - - if(!this.initialized) { - replayGuiList = new ReplayList(this, this.mc, this.width, this.height, 32, this.height - 64, 36); - this.initialized = true; - } else { - this.replayGuiList.setDimensions(this.width, this.height, 32, this.height - 64); - } - - try { - if(fileReloader != null) { - fileReloader.interrupt(); - fileReloader.join(); - } - - fileReloader = new FileReloaderThread(); - fileReloader.start(); - } catch(Exception e) { - e.printStackTrace(); - } - - this.createButtons(); - } - - private void createButtons() { - @SuppressWarnings("unchecked") - List buttonList = this.buttonList; - buttonList.add(loadButton = new GuiButton(LOAD_BUTTON_ID, this.width / 2 - 154, this.height - 52, 73, 20, I18n.format("replaymod.gui.load"))); - buttonList.add(uploadButton = new GuiButton(UPLOAD_BUTTON_ID, this.width / 2 - 154 + 78, this.height - 52, 73, 20, I18n.format("replaymod.gui.upload"))); - buttonList.add(new GuiButton(FOLDER_BUTTON_ID, this.width / 2 + 4, this.height - 52, 150, 20, I18n.format("replaymod.gui.viewer.replayfolder"))); - buttonList.add(renameButton = new GuiButton(RENAME_BUTTON_ID, this.width / 2 - 154, this.height - 28, 72, 20, I18n.format("replaymod.gui.rename"))); - buttonList.add(deleteButton = new GuiButton(DELETE_BUTTON_ID, this.width / 2 - 76, this.height - 28, 72, 20, I18n.format("replaymod.gui.delete"))); - buttonList.add(new GuiButton(SETTINGS_BUTTON_ID, this.width / 2 + 4, this.height - 28, 72, 20, I18n.format("replaymod.gui.settings"))); - buttonList.add(new GuiButton(CANCEL_BUTTON_ID, this.width / 2 + 4 + 78, this.height - 28, 72, 20, I18n.format("replaymod.gui.cancel"))); - setButtonsEnabled(false); - } - - @Override - public void handleMouseInput() throws IOException { - super.handleMouseInput(); - this.replayGuiList.handleMouseInput(); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - super.mouseClicked(mouseX, mouseY, mouseButton); - this.replayGuiList.mouseClicked(mouseX, mouseY, mouseButton); - } - - @Override - protected void mouseReleased(int mouseX, int mouseY, int state) { - super.mouseReleased(mouseX, mouseY, state); - this.replayGuiList.mouseReleased(mouseX, mouseY, state); - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - this.drawDefaultBackground(); - this.replayGuiList.drawScreen(mouseX, mouseY, partialTicks); - this.drawCenteredString(this.fontRendererObj, I18n.format("replaymod.gui.replayviewer"), this.width / 2, 20, 16777215); - - super.drawScreen(mouseX, mouseY, partialTicks); - - if(uploadButton.isMouseOver() && !uploadButton.enabled && loadButton.enabled) { - if(currentFileUploaded) { - ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.viewer.alreadyuploaded"), this, Color.RED); - } - } - } - - @Override - protected void actionPerformed(GuiButton button) throws IOException { - if(button.enabled) { - if(button.id == LOAD_BUTTON_ID) { - loadReplay(replayGuiList.selected); - } else if(button.id == CANCEL_BUTTON_ID) { - mc.displayGuiScreen(null); - } else if(button.id == DELETE_BUTTON_ID) { - String s = ((GuiReplayListEntry)replayGuiList.getListEntry(replayGuiList.selected)).getFileInfo().getName(); - - if(s != null) { - delete_file = true; - GuiYesNo guiyesno = getYesNoGui(this, s, 1); - this.mc.displayGuiScreen(guiyesno); - } - } else if(button.id == SETTINGS_BUTTON_ID) { - new GuiReplaySettings(this, ReplayMod.instance.getSettingsRegistry()).display(); - } else if(button.id == RENAME_BUTTON_ID) { - File file = replayFileList.get(replayGuiList.selected).first().first(); - new GuiRenameReplay(this, file).display(); - } else if(button.id == UPLOAD_BUTTON_ID) { - File file = replayFileList.get(replayGuiList.selected).first().first(); - this.mc.displayGuiScreen(new GuiUploadFile(file, this)); - } else if(button.id == FOLDER_BUTTON_ID) { - File file1 = ReplayFileIO.getReplayFolder(); - - String s = file1.getAbsolutePath(); - - if(Util.getOSType() == Util.EnumOS.OSX) { - try { - Runtime.getRuntime().exec(new String[]{"/usr/bin/open", s}); - return; - } catch (IOException e) { - LogManager.getLogger().error("Cannot open file", e); - } - } else if(Util.getOSType() == Util.EnumOS.WINDOWS) { - String s1 = String.format("cmd.exe /C start \"Open file\" \"%s\"", s); - - try { - Runtime.getRuntime().exec(s1); - return; - } catch(IOException e) { - LogManager.getLogger().error("Cannot open file", e); + }).setSize(73, 20).setI18nLabel("replaymod.gui.rename").setDisabled(); + public final GuiButton deleteButton = new GuiButton().onClick(new Runnable() { + @Override + public void run() { + String name = list.getSelected().name.getText(); + GuiYesNoPopup popup = GuiYesNoPopup.open(GuiReplayViewer.this, + new GuiLabel().setI18nText("replaymod.gui.viewer.delete.linea").setColor(Colors.BLACK), + new GuiLabel().setI18nText("replaymod.gui.viewer.delete.lineb", name + ChatFormatting.RESET).setColor(Colors.BLACK) + ).setYesI18nLabel("replaymod.gui.delete").setNoI18nLabel("replaymod.gui.cancel"); + Futures.addCallback(popup.getFuture(), new FutureCallback() { + @Override + public void onSuccess(Boolean delete) { + if (delete) { + try { + FileUtils.forceDelete(list.getSelected().file); + } catch (IOException e) { + e.printStackTrace(); + } + list.load(); } } - boolean flag = false; - - try { - Desktop.getDesktop().browse(file1.toURI()); - } catch(Throwable throwable) { - flag = true; + @Override + public void onFailure(Throwable t) { + t.printStackTrace(); } - - if(flag) { - Sys.openURL("file://" + s); - } - } + }); } + }).setSize(73, 20).setI18nLabel("replaymod.gui.delete").setDisabled(); + + public final GuiButton settingsButton = new GuiButton().onClick(new Runnable() { + @Override + public void run() { + new GuiReplaySettings(toMinecraft(), mod.getCore().getSettingsRegistry()).display(); + } + }).setSize(73, 20).setI18nLabel("replaymod.gui.settings"); + + public final GuiButton cancelButton = new GuiButton().onClick(new Runnable() { + @Override + public void run() { + getMinecraft().displayGuiScreen(null); + } + }).setSize(73, 20).setI18nLabel("replaymod.gui.cancel");; + + public final GuiPanel replayButtonPanel = new GuiPanel().setLayout(new GridLayout().setSpacingX(5).setSpacingY(5) + .setColumns(2)).addElements(null, loadButton, new GuiPanel() /* Upload */, renameButton, deleteButton); + public final GuiPanel generalButtonPanel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(5)) + .addElements(null, folderButton, new GuiPanel().setLayout(new HorizontalLayout().setSpacing(5)) + .addElements(null, settingsButton, cancelButton)); + public final GuiPanel buttonPanel = new GuiPanel(this).setLayout(new HorizontalLayout().setSpacing(6)) + .addElements(null, replayButtonPanel, generalButtonPanel); + + public GuiReplayViewer(ReplayModReplay mod) { + this.mod = mod; + + setTitle(new GuiLabel().setI18nText("replaymod.gui.replayviewer")); + + setLayout(new CustomLayout() { + @Override + protected void layout(GuiReplayViewer container, int width, int height) { + pos(buttonPanel, width / 2 - width(buttonPanel) / 2, height - 10 - height(buttonPanel)); + + pos(list, 0, 30); + size(list, width, y(buttonPanel) - 10 - y(list)); + } + }); } @Override - public void confirmClicked(boolean result, int id) { - if(this.delete_file) { - this.delete_file = false; + protected GuiReplayViewer getThis() { + return this; + } - if(result) { - try { - FileUtils.forceDelete(replayFileList.get(replayGuiList.selected).first().first()); - } catch (IOException e) { - e.printStackTrace(); - } - replayFileList.remove(replayGuiList.selected); - replayGuiList.selected = -1; + private final GuiImage defaultThumbnail = new GuiImage().setTexture(ResourceHelper.getDefaultThumbnail()); + public class GuiReplayEntry extends AbstractGuiContainer implements Comparable { + public final File file; + public final GuiLabel name = new GuiLabel(); + public final GuiLabel server = new GuiLabel().setColor(Colors.LIGHT_GRAY); + public final GuiLabel date = new GuiLabel().setColor(Colors.LIGHT_GRAY); + public final GuiPanel infoPanel = new GuiPanel(this).setLayout(new VerticalLayout().setSpacing(2)) + .addElements(null, name, server, date); + public final GuiImage thumbnail; + public final GuiLabel duration = new GuiLabel(); + public final GuiPanel durationPanel = new GuiPanel().setBackgroundColor(Colors.HALF_TRANSPARENT) + .addElements(null, duration).setLayout(new CustomLayout() { + @Override + protected void layout(GuiPanel container, int width, int height) { + pos(duration, 2, 2); + } + + @Override + public ReadableDimension calcMinSize(GuiContainer container) { + ReadableDimension dimension = duration.calcMinSize(); + return new Dimension(dimension.getWidth() + 2, dimension.getHeight() + 2); + } + }); + + private final long dateMillis; + + public GuiReplayEntry(File file, ReplayMetaData metaData, BufferedImage thumbImage) { + this.file = file; + + name.setText(ChatFormatting.UNDERLINE + FilenameUtils.getBaseName(file.getName())); + if (Strings.isEmpty(metaData.getServerName())) { + server.setI18nText("replaymod.gui.iphidden").setColor(Colors.DARK_RED); + } else { + server.setText(metaData.getServerName()); } + dateMillis = metaData.getDate(); + date.setText(new SimpleDateFormat().format(new Date(dateMillis))); + if (thumbImage == null) { + thumbnail = new GuiImage(defaultThumbnail).setSize(30 * 16 / 9, 30); + addElements(null, thumbnail); + } else { + thumbnail = new GuiImage(this).setTexture(thumbImage).setSize(30 * 16 / 9, 30); + } + duration.setText(DurationUtils.convertSecondsToShortString(metaData.getDuration() / 1000)); + addElements(null, durationPanel); - this.mc.displayGuiScreen(this); + setLayout(new CustomLayout() { + @Override + protected void layout(GuiReplayEntry container, int width, int height) { + pos(thumbnail, 0, 0); + x(durationPanel, width(thumbnail) - width(durationPanel)); + y(durationPanel, height(thumbnail) - height(durationPanel)); + + pos(infoPanel, width(thumbnail) + 5, 0); + } + + @Override + public ReadableDimension calcMinSize(GuiContainer container) { + return new Dimension(300, thumbnail.getMinSize().getHeight()); + } + }); } - } - - @Override - public void updateScreen() { - super.updateScreen(); - while (!loadedReplaysQueue.isEmpty()) { - loadedReplaysQueue.poll().run(); - } - } - - private boolean currentFileUploaded = false; - - public void setButtonsEnabled(boolean b) { - loadButton.enabled = b; - - if(b) { - currentFileUploaded = ReplayMod.uploadedFileHandler.isUploaded(replayFileList.get(replayGuiList.selected).first().first()); - uploadButton.enabled = !currentFileUploaded; - } else { - uploadButton.enabled = false; - } - - - renameButton.enabled = b; - deleteButton.enabled = b; - } - - public void loadReplay(int id) { - mc.displayGuiScreen(null); - - try { - mod.startReplay(replayFileList.get(id).first().first()); - } catch(Exception e) { - e.printStackTrace(); - } - - } - - private void addEntry(File file, ReplayMetaData metaData, File thumb) { - final Pair, File> p = Pair.of(Pair.of(file, metaData), thumb); - final int index = getInsertionIndex(p, replayFileList); - - replayFileList.add(index, p); - - final FileInfo fileInfo = new FileInfo(-1, p.first().second(), null, null, - -1, -1, -1, FilenameUtils.getBaseName(p.first().first().getName()), true, -1); - - replayGuiList.addEntry(index, new GuiReplayListEntry(replayGuiList, fileInfo, p.second())); - } - - private static FileAgeComparator fileAgeComparator = new FileAgeComparator(); - - public static class FileAgeComparator implements Comparator, File>> { @Override - public int compare(Pair, File> o1, Pair, File> o2) { - try { - return new Date(o2.first().second().getDate()).compareTo(new Date(o1.first().second().getDate())); - } catch(Exception e) { - return 0; - } + protected GuiReplayEntry getThis() { + return this; + } + + @Override + public int compareTo(GuiReplayEntry o) { + return Long.compare(o.dateMillis, dateMillis); } } - private int getInsertionIndex(Pair, File> p, List, File>> list) { - List, File>> nl = new ArrayList, File>>(list); - - nl.add(p); - Collections.sort(nl, fileAgeComparator); - - return nl.indexOf(p); - } +// TODO: Online module +// if(uploadButton.isMouseOver() && !uploadButton.enabled && loadButton.enabled) { +// if(currentFileUploaded) { +// ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.viewer.alreadyuploaded"), this, Color.RED); +// } +// } +// +// private boolean currentFileUploaded = false; +// +// public void setButtonsEnabled(boolean b) { +// loadButton.enabled = b; +// +// if(b) { +// currentFileUploaded = ReplayMod.uploadedFileHandler.isUploaded(replayFileList.get(replayGuiList.selected).first().first()); +// uploadButton.enabled = !currentFileUploaded; +// } else { +// uploadButton.enabled = false; +// } +// +// +// renameButton.enabled = b; +// deleteButton.enabled = b; +// } } diff --git a/src/main/java/com/replaymod/replay/gui/screen/ReplayList.java b/src/main/java/com/replaymod/replay/gui/screen/ReplayList.java deleted file mode 100755 index c08f517b..00000000 --- a/src/main/java/com/replaymod/replay/gui/screen/ReplayList.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.replaymod.replay.gui.screen; - -import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended; -import net.minecraft.client.Minecraft; - -public class ReplayList extends GuiReplayListExtended { - - private GuiReplayViewer parent; - - public ReplayList(GuiReplayViewer parent, Minecraft mcIn, - int p_i45010_2_, int p_i45010_3_, int p_i45010_4_, int p_i45010_5_, - int p_i45010_6_) { - super(mcIn, p_i45010_2_, p_i45010_3_, p_i45010_4_, p_i45010_5_, - p_i45010_6_); - - this.parent = parent; - } - - @Override - protected void elementClicked(int slotIndex, boolean isDoubleClick, - int mouseX, int mouseY) { - super.elementClicked(slotIndex, isDoubleClick, mouseX, mouseY); - parent.setButtonsEnabled(true); - if(isDoubleClick) { - parent.loadReplay(slotIndex); - } - } - -} diff --git a/src/main/java/com/replaymod/replay/handler/GuiHandler.java b/src/main/java/com/replaymod/replay/handler/GuiHandler.java index 8ad74d1f..b936b709 100644 --- a/src/main/java/com/replaymod/replay/handler/GuiHandler.java +++ b/src/main/java/com/replaymod/replay/handler/GuiHandler.java @@ -92,7 +92,7 @@ public class GuiHandler { if (event.gui instanceof GuiMainMenu) { if (event.button.id == BUTTON_REPLAY_VIEWER) { - mc.displayGuiScreen(new GuiReplayViewer(mod)); + new GuiReplayViewer(mod).display(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java index e7b636e3..6a086052 100755 --- a/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java +++ b/src/main/java/eu/crushedpixel/replaymod/gui/online/GuiUploadFile.java @@ -116,7 +116,7 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener { if(!correctFile) { Logger logger = LogManager.getLogger(); logger.error("Invalid file provided to upload"); - mc.displayGuiScreen(parent); + parent.display(); replayFile = null; return; } @@ -134,12 +134,12 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener { @Override public void initGui() { if(replayFile == null) { - mc.displayGuiScreen(parent); + parent.display(); return; } if(!ReplayMod.apiClient.isLoggedIn()) { - mc.displayGuiScreen(new GuiLoginPrompt(parent, this, true).toMinecraft()); + mc.displayGuiScreen(new GuiLoginPrompt(parent.toMinecraft(), this, true).toMinecraft()); return; } @@ -289,7 +289,7 @@ public class GuiUploadFile extends GuiScreen implements ProgressUpdateListener { protected void actionPerformed(GuiButton button) throws IOException { if(!button.enabled) return; if(button.id == GuiConstants.UPLOAD_BACK_BUTTON) { - mc.displayGuiScreen(parent); + parent.display(); } else if(button.id == GuiConstants.UPLOAD_START_BUTTON) { final String name = this.name.getText().trim(); new Thread(new Runnable() { diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 42c3e46d..d6fb0196 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -149,9 +149,7 @@ replaymod.gui.viewer.alreadyuploaded=This Replay has already been uploaded replaymod.gui.viewer.delete.linea=Are you sure you want to delete this replay? replaymod.gui.viewer.delete.failed1=Your OS did not allow us to move the replay. There is replaymod.gui.viewer.delete.failed2=nothing we can do about this. You have to do it yourself. - -#The Replay file name is inserted before the following string, e.g. "Some Replay will be lost forever!..." -replaymod.gui.viewer.delete.lineb=will be lost forever! (a long time!) +replaymod.gui.viewer.delete.lineb='%1$s' will be lost forever! (a long time!) replaymod.gui.viewer.download.title=Downloading Replay File... replaymod.gui.viewer.download.message=Please wait while "%1$s" is being downloaded.