Skip to content

Commit

Permalink
FabricMC/Enigma#532 - rai version
Browse files Browse the repository at this point in the history
  • Loading branch information
ix0rai committed Apr 16, 2024
1 parent df33132 commit 2969043
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 50 deletions.
19 changes: 8 additions & 11 deletions enigma-swing/src/main/java/org/quiltmc/enigma/gui/Gui.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.quiltmc.enigma.gui.panel.EditorPanel;
import org.quiltmc.enigma.gui.panel.IdentifierPanel;
import org.quiltmc.enigma.gui.renderer.MessageListCellRenderer;
import org.quiltmc.enigma.gui.util.ExtensionFileFilter;
import org.quiltmc.enigma.gui.util.GuiUtil;
import org.quiltmc.enigma.gui.util.LanguageUtil;
import org.quiltmc.enigma.gui.util.ScaleUtil;
Expand Down Expand Up @@ -95,8 +96,7 @@ public class Gui {
private final NotificationManager notificationManager;

public final JFileChooser jarFileChooser;
public final JFileChooser tinyMappingsFileChooser;
public final JFileChooser enigmaMappingsFileChooser;
public final JFileChooser mappingsFileChooser;
public final JFileChooser exportSourceFileChooser;
public final JFileChooser exportJarFileChooser;
public final SearchDialog searchDialog;
Expand All @@ -118,8 +118,7 @@ public Gui(EnigmaProfile profile, Set<EditableType> editableTypes, boolean visib
this.splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.centerPanel, this.dockerManager.getRightDock());
this.splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.dockerManager.getLeftDock(), this.splitRight);
this.jarFileChooser = new JFileChooser();
this.tinyMappingsFileChooser = new JFileChooser();
this.enigmaMappingsFileChooser = new JFileChooser();
this.mappingsFileChooser = new JFileChooser();
this.exportSourceFileChooser = new JFileChooser();
this.exportJarFileChooser = new JFileChooser();
this.connectionStatusLabel = new JLabel();
Expand Down Expand Up @@ -165,10 +164,6 @@ private void setupUi() {
this.setupDockers();

this.jarFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
this.tinyMappingsFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

this.enigmaMappingsFileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
this.enigmaMappingsFileChooser.setAcceptAllFileFilterUsed(false);

this.exportSourceFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
this.exportSourceFileChooser.setAcceptAllFileFilterUsed(false);
Expand Down Expand Up @@ -367,7 +362,7 @@ public void updateAllClasses() {
}

public void setMappingsFile(Path path) {
this.enigmaMappingsFileChooser.setSelectedFile(path != null ? path.toFile() : null);
this.mappingsFileChooser.setSelectedFile(path != null ? path.toFile() : null);
this.updateUiState();
}

Expand Down Expand Up @@ -491,8 +486,10 @@ public void showDiscardDiag(IntFunction<Void> callback, String... options) {
}

public CompletableFuture<Void> saveMapping() {
if (this.enigmaMappingsFileChooser.getSelectedFile() != null || this.enigmaMappingsFileChooser.showSaveDialog(this.mainWindow.getFrame()) == JFileChooser.APPROVE_OPTION) {
return this.controller.saveMappings(this.enigmaMappingsFileChooser.getSelectedFile().toPath());
ExtensionFileFilter.setupFileChooser(this.mappingsFileChooser, this.controller.getLoadedMappingFormat());

if (this.mappingsFileChooser.getSelectedFile() != null || this.mappingsFileChooser.showSaveDialog(this.mainWindow.getFrame()) == JFileChooser.APPROVE_OPTION) {
return this.controller.saveMappings(ExtensionFileFilter.getSavePath(this.mappingsFileChooser));
}

return CompletableFuture.completedFuture(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
import org.quiltmc.enigma.util.validation.ValidationContext;
import org.tinylog.Logger;

import javax.annotation.Nullable;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import java.awt.Desktop;
Expand Down Expand Up @@ -611,10 +612,16 @@ public Enigma getEnigma() {
return this.enigma;
}

@Nullable
public StatsGenerator getStatsGenerator() {
return this.statsGenerator;
}

@Nullable
public MappingFormat getLoadedMappingFormat() {
return loadedMappingFormat;
}

public void createClient(String username, String ip, int port, char[] password) throws IOException {
this.client = new IntegratedEnigmaClient(this, ip, port);
this.client.connect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.quiltmc.enigma.gui.dialog.StatsDialog;
import org.quiltmc.enigma.gui.dialog.decompiler.DecompilerSettingsDialog;
import org.quiltmc.enigma.gui.dialog.keybind.ConfigureKeyBindsDialog;
import org.quiltmc.enigma.gui.util.ExtensionFileFilter;
import org.quiltmc.enigma.gui.util.GuiUtil;
import org.quiltmc.enigma.gui.util.LanguageUtil;
import org.quiltmc.enigma.gui.util.ScaleUtil;
Expand Down Expand Up @@ -222,8 +223,7 @@ public void updateUiState() {

this.jarCloseItem.setEnabled(jarOpen);
this.openMappingsItem.setEnabled(jarOpen);
this.saveMappingsItem.setEnabled(jarOpen && this.gui.enigmaMappingsFileChooser.getSelectedFile() != null && connectionState != ConnectionState.CONNECTED);
this.saveMappingsAsMenu.setEnabled(jarOpen);
this.saveMappingsItem.setEnabled(jarOpen && this.gui.mappingsFileChooser.getSelectedFile() != null && connectionState != ConnectionState.CONNECTED); this.saveMappingsAsMenu.setEnabled(jarOpen);
this.closeMappingsItem.setEnabled(jarOpen);
this.reloadMappingsItem.setEnabled(jarOpen);
this.reloadAllItem.setEnabled(jarOpen);
Expand Down Expand Up @@ -324,7 +324,7 @@ private void onMaxRecentFilesClicked() {
}

private void onSaveMappingsClicked() {
this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath());
this.gui.getController().saveMappings(this.gui.mappingsFileChooser.getSelectedFile().toPath());
}

private void openMappingsDiscardPrompt(Runnable then) {
Expand Down Expand Up @@ -469,10 +469,10 @@ private void onGithubClicked() {
}

private void onOpenMappingsClicked() {
this.gui.enigmaMappingsFileChooser.setCurrentDirectory(new File(Config.main().stats.lastSelectedDir.value()));
if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
File selectedFile = this.gui.enigmaMappingsFileChooser.getSelectedFile();
Config.main().stats.lastSelectedDir.setValue(this.gui.enigmaMappingsFileChooser.getCurrentDirectory().toString(), true);
this.gui.mappingsFileChooser.setCurrentDirectory(new File(Config.main().stats.lastSelectedDir.value()));
if (this.gui.mappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
File selectedFile = this.gui.mappingsFileChooser.getSelectedFile();
Config.main().stats.lastSelectedDir.setValue(this.gui.mappingsFileChooser.getCurrentDirectory().toString(), true);

MappingFormat format = MappingFormat.parseFromFile(selectedFile.toPath());
if (format.getReader() != null) {
Expand Down Expand Up @@ -549,15 +549,18 @@ private static void prepareSaveMappingsAsMenu(JMenu saveMappingsAsMenu, JMenuIte
if (format.getWriter() != null) {
JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT)));
item.addActionListener(event -> {
// TODO: Use a specific file chooser for it
if (gui.enigmaMappingsFileChooser.getCurrentDirectory() == null) {
gui.enigmaMappingsFileChooser.setCurrentDirectory(new File(Config.main().stats.lastSelectedDir.value()));
JFileChooser fileChooser = gui.mappingsFileChooser;
ExtensionFileFilter.setupFileChooser(fileChooser, format);

if (fileChooser.getCurrentDirectory() == null) {
fileChooser.setCurrentDirectory(new File(Config.main().stats.lastSelectedDir.value()));
}

if (gui.enigmaMappingsFileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
gui.getController().saveMappings(gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format);
if (fileChooser.showSaveDialog(gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
Path savePath = ExtensionFileFilter.getSavePath(fileChooser);
gui.getController().saveMappings(savePath, format);
saveMappingsItem.setEnabled(true);
Config.main().stats.lastSelectedDir.setValue(gui.enigmaMappingsFileChooser.getCurrentDirectory().toString(), true);
Config.main().stats.lastSelectedDir.setValue(fileChooser.getCurrentDirectory().toString());
}
});
saveMappingsAsMenu.add(item);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.quiltmc.enigma.gui.util;

import org.quiltmc.enigma.api.translation.mapping.serde.MappingFormat;
import org.quiltmc.enigma.util.I18n;

import javax.annotation.Nullable;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.StringJoiner;

public final class ExtensionFileFilter extends FileFilter {
private final String formatName;
private final List<String> extensions;

/**
* Constructs an {@code ExtensionFileFilter}.
*
* @param formatName the human-readable name of the file format
* @param extensions the file extensions with their leading dots (e.g. {@code .txt})
*/
public ExtensionFileFilter(String formatName, List<String> extensions) {
this.formatName = formatName;
this.extensions = extensions;
}

public List<String> getExtensions() {
return extensions;
}

@Override
public boolean accept(File f) {
// Always accept directories so the user can see them.
if (f.isDirectory()) {
return true;
}

for (String extension : extensions) {
if (f.getName().endsWith(extension)) {
return true;
}
}

return false;
}

@Override
public String getDescription() {
var joiner = new StringJoiner(", ");

for (String extension : extensions) {
joiner.add("*" + extension);
}

return I18n.translateFormatted("menu.file.mappings.file_filter", formatName, joiner.toString());
}

/**
* Sets up a file chooser with a mapping format. This method resets the choosable filters,
* and adds and selects a new filter based on the provided mapping format.
*
* @param fileChooser the file chooser to set up
* @param format the mapping format to use. if {@code null}, the file chooser will accept only directories
*/
public static void setupFileChooser(JFileChooser fileChooser, @Nullable MappingFormat format) {
if (format == null) {
format = MappingFormat.ENIGMA_DIRECTORY;
}

// Remove previous custom filters.
fileChooser.resetChoosableFileFilters();

if (format.getFileType().isDirectory()) {
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
String formatName = I18n.translate("mapping_format." + format.name().toLowerCase());
var filter = new ExtensionFileFilter(formatName, format.getFileType().getExtensions());
// Add our new filter to the list...
fileChooser.addChoosableFileFilter(filter);
// ...and choose it as the default.
fileChooser.setFileFilter(filter);
}
}

/**
* Fixes a missing file extension in a save file path when the selected filter
* is an {@code ExtensionFileFilter}.
*
* @param fileChooser the file chooser to check
* @return the fixed path
*/
public static Path getSavePath(JFileChooser fileChooser) {
Path savePath = fileChooser.getSelectedFile().toPath();

if (fileChooser.getFileFilter() instanceof ExtensionFileFilter extensionFilter) {
// Check that the file name ends with the extension.
String fileName = savePath.getFileName().toString();
boolean hasExtension = false;

for (String extension : extensionFilter.getExtensions()) {
if (fileName.endsWith(extension)) {
hasExtension = true;
break;
}
}

if (!hasExtension) {
String defaultExtension = extensionFilter.getExtensions().get(0);
// If not, add the extension.
savePath = savePath.resolveSibling(fileName + defaultExtension);
// Store the adjusted file, so that it shows up properly
// the next time this dialog is used.
fileChooser.setSelectedFile(savePath.toFile());
}
}

return savePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,32 @@
import org.quiltmc.enigma.api.translation.mapping.serde.tinyv2.TinyV2Reader;
import org.quiltmc.enigma.api.translation.mapping.serde.tinyv2.TinyV2Writer;
import org.quiltmc.enigma.api.translation.mapping.tree.EntryTree;
import org.quiltmc.enigma.impl.translation.FileType;

import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;

public enum MappingFormat {
ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE),
ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY),
ENIGMA_ZIP(EnigmaMappingsWriter.ZIP, EnigmaMappingsReader.ZIP),
TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader()),
SRG_FILE(SrgMappingsWriter.INSTANCE, null),
PROGUARD(null, ProguardMappingsReader.INSTANCE);
ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE, FileType.ENIGMA_MAPPING),
ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY, FileType.ENIGMA_DIRECTORY),
ENIGMA_ZIP(EnigmaMappingsWriter.ZIP, EnigmaMappingsReader.ZIP, FileType.ENIGMA_ZIP),
TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader(), FileType.TINY_V2),
SRG_FILE(SrgMappingsWriter.INSTANCE, null, FileType.SRG),
PROGUARD(null, ProguardMappingsReader.INSTANCE, FileType.PROGUARD);

private final MappingsWriter writer;
private final MappingsReader reader;
private final FileType fileType;

MappingFormat(MappingsWriter writer, MappingsReader reader) {
MappingFormat(MappingsWriter writer, MappingsReader reader, FileType fileType) {
this.writer = writer;
this.reader = reader;
this.fileType = fileType;
}

public void write(EntryTree<EntryMapping> mappings, Path path, MappingSaveParameters saveParameters) {
Expand Down Expand Up @@ -90,34 +96,47 @@ public MappingsReader getReader() {
return this.reader;
}

public FileType getFileType() {
return this.fileType;
}

/**
* Determines the mapping format of the provided file. Checks all formats, and returns {@link #PROGUARD} if none match.
* Determines the mapping format of the provided file. Checks all formats according to their {@link #getFileType()} file extensions.
* If the file is a directory, it will check the first file in the directory.
* Will return {@link #PROGUARD} if no format is found for single files, and {@link #ENIGMA_DIRECTORY} if no format is found for directories.
* @param file the file to analyse
* @apiNote Any directory is considered to be the {@link #ENIGMA_DIRECTORY} format.
* Proguard does not have an explicit file extension, so it is the fallback.
* @return the mapping format of the file.
*/
public static MappingFormat parseFromFile(Path file) {
if (Files.isDirectory(file)) {
return ENIGMA_DIRECTORY;
} else {
switch (MoreFiles.getFileExtension(file).toLowerCase()) {
case "zip" -> {
return ENIGMA_ZIP;
}
case "mapping", "mappings" -> {
return ENIGMA_FILE;
}
case "tiny" -> {
return TINY_V2;
}
case "tsrg" -> {
return SRG_FILE;
try {
File firstFile = Arrays.stream(Objects.requireNonNull(file.toFile().listFiles())).findFirst().orElseThrow();

for (MappingFormat format : values()) {
if (!format.getFileType().isDirectory()) {
continue;
}

String extension = MoreFiles.getFileExtension(firstFile.toPath()).toLowerCase();
if (format.fileType.getExtensions().contains(extension)) {
return format;
}
}
default -> {
return PROGUARD;

return ENIGMA_DIRECTORY;
} catch (Exception e) {
return ENIGMA_DIRECTORY;
}
} else {
String extension = MoreFiles.getFileExtension(file).toLowerCase();

for (MappingFormat format : values()) {
if (format.fileType.getExtensions().contains(extension)) {
return format;
}
}
}

return PROGUARD;
}
}
Loading

0 comments on commit 2969043

Please sign in to comment.