summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui')
-rw-r--r--src/main/java/cuchaz/enigma/gui/ClassSelector.java5
-rw-r--r--src/main/java/cuchaz/enigma/gui/CodeReader.java57
-rw-r--r--src/main/java/cuchaz/enigma/gui/Gui.java80
-rw-r--r--src/main/java/cuchaz/enigma/gui/GuiController.java209
-rw-r--r--src/main/java/cuchaz/enigma/gui/GuiTricks.java42
-rw-r--r--src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java44
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java4
-rw-r--r--src/main/java/cuchaz/enigma/gui/elements/MenuBar.java45
-rw-r--r--src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java2
-rw-r--r--src/main/java/cuchaz/enigma/gui/panels/PanelObf.java6
10 files changed, 172 insertions, 322 deletions
diff --git a/src/main/java/cuchaz/enigma/gui/ClassSelector.java b/src/main/java/cuchaz/enigma/gui/ClassSelector.java
index 8863386..c3b7288 100644
--- a/src/main/java/cuchaz/enigma/gui/ClassSelector.java
+++ b/src/main/java/cuchaz/enigma/gui/ClassSelector.java
@@ -17,14 +17,13 @@ import com.google.common.collect.Maps;
17import com.google.common.collect.Multimap; 17import com.google.common.collect.Multimap;
18import cuchaz.enigma.gui.node.ClassSelectorClassNode; 18import cuchaz.enigma.gui.node.ClassSelectorClassNode;
19import cuchaz.enigma.gui.node.ClassSelectorPackageNode; 19import cuchaz.enigma.gui.node.ClassSelectorPackageNode;
20import cuchaz.enigma.mapping.entry.ClassEntry; 20import cuchaz.enigma.translation.representation.entry.ClassEntry;
21import cuchaz.enigma.throwables.IllegalNameException; 21import cuchaz.enigma.throwables.IllegalNameException;
22 22
23import javax.swing.*; 23import javax.swing.*;
24import javax.swing.event.CellEditorListener; 24import javax.swing.event.CellEditorListener;
25import javax.swing.event.ChangeEvent; 25import javax.swing.event.ChangeEvent;
26import javax.swing.tree.*; 26import javax.swing.tree.*;
27import java.awt.*;
28import java.awt.event.MouseAdapter; 27import java.awt.event.MouseAdapter;
29import java.awt.event.MouseEvent; 28import java.awt.event.MouseEvent;
30import java.util.*; 29import java.util.*;
@@ -32,7 +31,7 @@ import java.util.List;
32 31
33public class ClassSelector extends JTree { 32public class ClassSelector extends JTree {
34 33
35 public static final Comparator<ClassEntry> DEOBF_CLASS_COMPARATOR = Comparator.comparing(ClassEntry::getName); 34 public static final Comparator<ClassEntry> DEOBF_CLASS_COMPARATOR = Comparator.comparing(ClassEntry::getFullName);
36 private DefaultMutableTreeNode rootNodes; 35 private DefaultMutableTreeNode rootNodes;
37 private ClassSelectionListener selectionListener; 36 private ClassSelectionListener selectionListener;
38 private RenameSelectionListener renameSelectionListener; 37 private RenameSelectionListener renameSelectionListener;
diff --git a/src/main/java/cuchaz/enigma/gui/CodeReader.java b/src/main/java/cuchaz/enigma/gui/CodeReader.java
index 137c730..0810043 100644
--- a/src/main/java/cuchaz/enigma/gui/CodeReader.java
+++ b/src/main/java/cuchaz/enigma/gui/CodeReader.java
@@ -16,9 +16,8 @@ import cuchaz.enigma.Deobfuscator;
16import cuchaz.enigma.analysis.EntryReference; 16import cuchaz.enigma.analysis.EntryReference;
17import cuchaz.enigma.analysis.SourceIndex; 17import cuchaz.enigma.analysis.SourceIndex;
18import cuchaz.enigma.analysis.Token; 18import cuchaz.enigma.analysis.Token;
19import cuchaz.enigma.gui.highlight.SelectionHighlightPainter; 19import cuchaz.enigma.translation.representation.entry.ClassEntry;
20import cuchaz.enigma.mapping.entry.ClassEntry; 20import cuchaz.enigma.translation.representation.entry.Entry;
21import cuchaz.enigma.mapping.entry.Entry;
22import de.sciss.syntaxpane.DefaultSyntaxKit; 21import de.sciss.syntaxpane.DefaultSyntaxKit;
23 22
24import javax.swing.*; 23import javax.swing.*;
@@ -33,7 +32,6 @@ public class CodeReader extends JEditorPane {
33 private static final long serialVersionUID = 3673180950485748810L; 32 private static final long serialVersionUID = 3673180950485748810L;
34 33
35 private static final Object lock = new Object(); 34 private static final Object lock = new Object();
36 private SelectionHighlightPainter selectionHighlightPainter;
37 private SourceIndex sourceIndex; 35 private SourceIndex sourceIndex;
38 private SelectionListener selectionListener; 36 private SelectionListener selectionListener;
39 37
@@ -58,8 +56,6 @@ public class CodeReader extends JEditorPane {
58 } 56 }
59 } 57 }
60 }); 58 });
61
62 selectionHighlightPainter = new SelectionHighlightPainter();
63 } 59 }
64 60
65 // HACKHACK: someday we can update the main GUI to use this code reader 61 // HACKHACK: someday we can update the main GUI to use this code reader
@@ -144,7 +140,7 @@ public class CodeReader extends JEditorPane {
144 140
145 // decompile it 141 // decompile it
146 142
147 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getOutermostClassName()); 143 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getName());
148 String source = deobfuscator.getSource(sourceTree); 144 String source = deobfuscator.getSource(sourceTree);
149 setCode(source); 145 setCode(source);
150 sourceIndex = deobfuscator.getSourceIndex(sourceTree, source, ignoreBadTokens); 146 sourceIndex = deobfuscator.getSourceIndex(sourceTree, source, ignoreBadTokens);
@@ -155,52 +151,7 @@ public class CodeReader extends JEditorPane {
155 }).start(); 151 }).start();
156 } 152 }
157 153
158 public void navigateToClassDeclaration(ClassEntry classEntry) {
159
160 // navigate to the class declaration
161 Token token = sourceIndex.getDeclarationToken(classEntry);
162 if (token == null) {
163 // couldn't find the class declaration token, might be an anonymous class
164 // look for any declaration in that class instead
165 for (Entry entry : sourceIndex.declarations()) {
166 if (entry.getOwnerClassEntry().equals(classEntry)) {
167 token = sourceIndex.getDeclarationToken(entry);
168 break;
169 }
170 }
171 }
172
173 if (token != null) {
174 navigateToToken(token);
175 } else {
176 // couldn't find anything =(
177 System.out.println("Unable to find declaration in source for " + classEntry);
178 }
179 }
180
181 public void navigateToToken(final Token token) {
182 navigateToToken(this, token, selectionHighlightPainter);
183 }
184
185 public void setHighlightedTokens(Iterable<Token> tokens, HighlightPainter painter) {
186 for (Token token : tokens) {
187 setHighlightedToken(token, painter);
188 }
189 }
190
191 public void setHighlightedToken(Token token, HighlightPainter painter) {
192 try {
193 getHighlighter().addHighlight(token.start, token.end, painter);
194 } catch (BadLocationException ex) {
195 throw new IllegalArgumentException(ex);
196 }
197 }
198
199 public void clearHighlights() {
200 getHighlighter().removeAllHighlights();
201 }
202
203 public interface SelectionListener { 154 public interface SelectionListener {
204 void onSelect(EntryReference<Entry, Entry> reference); 155 void onSelect(EntryReference<Entry<?>, Entry<?>> reference);
205 } 156 }
206} 157}
diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java
index 53500aa..d119735 100644
--- a/src/main/java/cuchaz/enigma/gui/Gui.java
+++ b/src/main/java/cuchaz/enigma/gui/Gui.java
@@ -29,9 +29,9 @@ import cuchaz.enigma.gui.panels.PanelDeobf;
29import cuchaz.enigma.gui.panels.PanelEditor; 29import cuchaz.enigma.gui.panels.PanelEditor;
30import cuchaz.enigma.gui.panels.PanelIdentifier; 30import cuchaz.enigma.gui.panels.PanelIdentifier;
31import cuchaz.enigma.gui.panels.PanelObf; 31import cuchaz.enigma.gui.panels.PanelObf;
32import cuchaz.enigma.mapping.*;
33import cuchaz.enigma.mapping.entry.*;
34import cuchaz.enigma.throwables.IllegalNameException; 32import cuchaz.enigma.throwables.IllegalNameException;
33import cuchaz.enigma.translation.mapping.AccessModifier;
34import cuchaz.enigma.translation.representation.entry.*;
35import cuchaz.enigma.utils.Utils; 35import cuchaz.enigma.utils.Utils;
36import de.sciss.syntaxpane.DefaultSyntaxKit; 36import de.sciss.syntaxpane.DefaultSyntaxKit;
37 37
@@ -44,8 +44,8 @@ import javax.swing.tree.TreeNode;
44import javax.swing.tree.TreePath; 44import javax.swing.tree.TreePath;
45import java.awt.*; 45import java.awt.*;
46import java.awt.event.*; 46import java.awt.event.*;
47import java.io.File;
48import java.io.IOException; 47import java.io.IOException;
48import java.nio.file.Path;
49import java.util.*; 49import java.util.*;
50import java.util.List; 50import java.util.List;
51import java.util.function.Function; 51import java.util.function.Function;
@@ -58,7 +58,7 @@ public class Gui {
58 58
59 private final MenuBar menuBar; 59 private final MenuBar menuBar;
60 // state 60 // state
61 public EntryReference<Entry, Entry> reference; 61 public EntryReference<Entry<?>, Entry<?>> reference;
62 public FileDialog jarFileChooser; 62 public FileDialog jarFileChooser;
63 public FileDialog tinyMappingsFileChooser; 63 public FileDialog tinyMappingsFileChooser;
64 public JFileChooser enigmaMappingsFileChooser; 64 public JFileChooser enigmaMappingsFileChooser;
@@ -222,7 +222,7 @@ public class Gui {
222 222
223 Object node = path.getLastPathComponent(); 223 Object node = path.getLastPathComponent();
224 if (node instanceof ReferenceTreeNode) { 224 if (node instanceof ReferenceTreeNode) {
225 ReferenceTreeNode<Entry, Entry> referenceNode = ((ReferenceTreeNode<Entry, Entry>) node); 225 ReferenceTreeNode<Entry<?>, Entry<?>> referenceNode = ((ReferenceTreeNode<Entry<?>, Entry<?>>) node);
226 if (referenceNode.getReference() != null) { 226 if (referenceNode.getReference() != null) {
227 navigateTo(referenceNode.getReference()); 227 navigateTo(referenceNode.getReference());
228 } else { 228 } else {
@@ -250,10 +250,10 @@ public class Gui {
250 tokens.setPreferredSize(new Dimension(0, 200)); 250 tokens.setPreferredSize(new Dimension(0, 200));
251 tokens.setMinimumSize(new Dimension(0, 200)); 251 tokens.setMinimumSize(new Dimension(0, 200));
252 JSplitPane callPanel = new JSplitPane( 252 JSplitPane callPanel = new JSplitPane(
253 JSplitPane.VERTICAL_SPLIT, 253 JSplitPane.VERTICAL_SPLIT,
254 true, 254 true,
255 new JScrollPane(callsTree), 255 new JScrollPane(callsTree),
256 new JScrollPane(tokens) 256 new JScrollPane(tokens)
257 ); 257 );
258 callPanel.setResizeWeight(1); // let the top side take all the slack 258 callPanel.setResizeWeight(1); // let the top side take all the slack
259 callPanel.resetToPreferredSizes(); 259 callPanel.resetToPreferredSizes();
@@ -368,9 +368,9 @@ public class Gui {
368 this.deobfPanel.deobfClasses.setClasses(deobfClasses); 368 this.deobfPanel.deobfClasses.setClasses(deobfClasses);
369 } 369 }
370 370
371 public void setMappingsFile(File file) { 371 public void setMappingsFile(Path path) {
372 this.enigmaMappingsFileChooser.setSelectedFile(file); 372 this.enigmaMappingsFileChooser.setSelectedFile(path != null ? path.toFile() : null);
373 this.menuBar.saveMappingsMenu.setEnabled(file != null); 373 this.menuBar.saveMappingsMenu.setEnabled(path != null);
374 } 374 }
375 375
376 public void setSource(String source) { 376 public void setSource(String source) {
@@ -427,7 +427,7 @@ public class Gui {
427 } 427 }
428 } 428 }
429 429
430 private void showReference(EntryReference<Entry, Entry> reference) { 430 private void showReference(EntryReference<Entry<?>, Entry<?>> reference) {
431 if (reference == null) { 431 if (reference == null) {
432 infoPanel.clearReference(); 432 infoPanel.clearReference();
433 return; 433 return;
@@ -453,29 +453,29 @@ public class Gui {
453 453
454 private void showLocalVariableEntry(LocalVariableEntry entry) { 454 private void showLocalVariableEntry(LocalVariableEntry entry) {
455 addNameValue(infoPanel, "Variable", entry.getName()); 455 addNameValue(infoPanel, "Variable", entry.getName());
456 addNameValue(infoPanel, "Class", entry.getOwnerClassEntry().getName()); 456 addNameValue(infoPanel, "Class", entry.getContainingClass().getFullName());
457 addNameValue(infoPanel, "Method", entry.getOwnerEntry().getName()); 457 addNameValue(infoPanel, "Method", entry.getParent().getName());
458 addNameValue(infoPanel, "Index", Integer.toString(entry.getIndex())); 458 addNameValue(infoPanel, "Index", Integer.toString(entry.getIndex()));
459 } 459 }
460 460
461 private void showClassEntry(ClassEntry entry) { 461 private void showClassEntry(ClassEntry entry) {
462 addNameValue(infoPanel, "Class", entry.getName()); 462 addNameValue(infoPanel, "Class", entry.getFullName());
463 addModifierComboBox(infoPanel, "Modifier", entry); 463 addModifierComboBox(infoPanel, "Modifier", entry);
464 } 464 }
465 465
466 private void showFieldEntry(FieldEntry entry) { 466 private void showFieldEntry(FieldEntry entry) {
467 addNameValue(infoPanel, "Field", entry.getName()); 467 addNameValue(infoPanel, "Field", entry.getName());
468 addNameValue(infoPanel, "Class", entry.getOwnerClassEntry().getName()); 468 addNameValue(infoPanel, "Class", entry.getParent().getFullName());
469 addNameValue(infoPanel, "TypeDescriptor", entry.getDesc().toString()); 469 addNameValue(infoPanel, "TypeDescriptor", entry.getDesc().toString());
470 addModifierComboBox(infoPanel, "Modifier", entry); 470 addModifierComboBox(infoPanel, "Modifier", entry);
471 } 471 }
472 472
473 private void showMethodEntry(MethodEntry entry) { 473 private void showMethodEntry(MethodEntry entry) {
474 if (entry.isConstructor()) { 474 if (entry.isConstructor()) {
475 addNameValue(infoPanel, "Constructor", entry.getOwnerClassEntry().getName()); 475 addNameValue(infoPanel, "Constructor", entry.getParent().getFullName());
476 } else { 476 } else {
477 addNameValue(infoPanel, "Method", entry.getName()); 477 addNameValue(infoPanel, "Method", entry.getName());
478 addNameValue(infoPanel, "Class", entry.getOwnerClassEntry().getName()); 478 addNameValue(infoPanel, "Class", entry.getParent().getFullName());
479 } 479 }
480 addNameValue(infoPanel, "MethodDescriptor", entry.getDesc().toString()); 480 addNameValue(infoPanel, "MethodDescriptor", entry.getDesc().toString());
481 addModifierComboBox(infoPanel, "Modifier", entry); 481 addModifierComboBox(infoPanel, "Modifier", entry);
@@ -494,7 +494,7 @@ public class Gui {
494 container.add(panel); 494 container.add(panel);
495 } 495 }
496 496
497 private JComboBox<Mappings.EntryModifier> addModifierComboBox(JPanel container, String name, Entry entry) { 497 private JComboBox<AccessModifier> addModifierComboBox(JPanel container, String name, Entry entry) {
498 if (!getController().entryIsInJar(entry)) 498 if (!getController().entryIsInJar(entry))
499 return null; 499 return null;
500 JPanel panel = new JPanel(); 500 JPanel panel = new JPanel();
@@ -502,7 +502,7 @@ public class Gui {
502 JLabel label = new JLabel(name + ":", JLabel.RIGHT); 502 JLabel label = new JLabel(name + ":", JLabel.RIGHT);
503 label.setPreferredSize(new Dimension(100, label.getPreferredSize().height)); 503 label.setPreferredSize(new Dimension(100, label.getPreferredSize().height));
504 panel.add(label); 504 panel.add(label);
505 JComboBox<Mappings.EntryModifier> combo = new JComboBox<>(Mappings.EntryModifier.values()); 505 JComboBox<AccessModifier> combo = new JComboBox<>(AccessModifier.values());
506 ((JLabel) combo.getRenderer()).setHorizontalAlignment(JLabel.LEFT); 506 ((JLabel) combo.getRenderer()).setHorizontalAlignment(JLabel.LEFT);
507 combo.setPreferredSize(new Dimension(100, label.getPreferredSize().height)); 507 combo.setPreferredSize(new Dimension(100, label.getPreferredSize().height));
508 combo.setSelectedIndex(getController().getDeobfuscator().getModifier(entry).ordinal()); 508 combo.setSelectedIndex(getController().getDeobfuscator().getModifier(entry).ordinal());
@@ -520,11 +520,13 @@ public class Gui {
520 boolean isToken = token != null; 520 boolean isToken = token != null;
521 521
522 reference = this.controller.getDeobfReference(token); 522 reference = this.controller.getDeobfReference(token);
523 boolean isClassEntry = isToken && reference.entry instanceof ClassEntry; 523
524 boolean isFieldEntry = isToken && reference.entry instanceof FieldEntry; 524 Entry<?> referenceEntry = reference != null ? reference.entry : null;
525 boolean isMethodEntry = isToken && reference.entry instanceof MethodEntry && !((MethodEntry) reference.entry).isConstructor(); 525 boolean isClassEntry = isToken && referenceEntry instanceof ClassEntry;
526 boolean isConstructorEntry = isToken && reference.entry instanceof MethodEntry && ((MethodEntry) reference.entry).isConstructor(); 526 boolean isFieldEntry = isToken && referenceEntry instanceof FieldEntry;
527 boolean isInJar = isToken && this.controller.entryIsInJar(reference.entry); 527 boolean isMethodEntry = isToken && referenceEntry instanceof MethodEntry && !((MethodEntry) referenceEntry).isConstructor();
528 boolean isConstructorEntry = isToken && referenceEntry instanceof MethodEntry && ((MethodEntry) referenceEntry).isConstructor();
529 boolean isInJar = isToken && this.controller.entryIsInJar(referenceEntry);
528 boolean isRenameable = isToken && this.controller.referenceIsRenameable(reference); 530 boolean isRenameable = isToken && this.controller.referenceIsRenameable(reference);
529 531
530 if (isToken) { 532 if (isToken) {
@@ -542,14 +544,14 @@ public class Gui {
542 this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousLocation()); 544 this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousLocation());
543 this.popupMenu.toggleMappingMenu.setEnabled(isRenameable); 545 this.popupMenu.toggleMappingMenu.setEnabled(isRenameable);
544 546
545 if (isToken && this.controller.entryHasDeobfuscatedName(reference.entry)) { 547 if (isToken && this.controller.entryHasDeobfuscatedName(referenceEntry)) {
546 this.popupMenu.toggleMappingMenu.setText("Reset to obfuscated"); 548 this.popupMenu.toggleMappingMenu.setText("Reset to obfuscated");
547 } else { 549 } else {
548 this.popupMenu.toggleMappingMenu.setText("Mark as deobfuscated"); 550 this.popupMenu.toggleMappingMenu.setText("Mark as deobfuscated");
549 } 551 }
550 } 552 }
551 553
552 public void navigateTo(Entry entry) { 554 public void navigateTo(Entry<?> entry) {
553 if (!this.controller.entryIsInJar(entry)) { 555 if (!this.controller.entryIsInJar(entry)) {
554 // entry is not in the jar. Ignore it 556 // entry is not in the jar. Ignore it
555 return; 557 return;
@@ -560,7 +562,7 @@ public class Gui {
560 this.controller.openDeclaration(entry); 562 this.controller.openDeclaration(entry);
561 } 563 }
562 564
563 private void navigateTo(EntryReference<Entry, Entry> reference) { 565 private void navigateTo(EntryReference<Entry<?>, Entry<?>> reference) {
564 if (!this.controller.entryIsInJar(reference.getLocationClassEntry())) { 566 if (!this.controller.entryIsInJar(reference.getLocationClassEntry())) {
565 return; 567 return;
566 } 568 }
@@ -613,7 +615,7 @@ public class Gui {
613 String newName = text.getText(); 615 String newName = text.getText();
614 if (saveName && newName != null && !newName.isEmpty()) { 616 if (saveName && newName != null && !newName.isEmpty()) {
615 try { 617 try {
616 this.controller.rename(reference, newName); 618 this.controller.rename(reference, newName, true);
617 } catch (IllegalNameException ex) { 619 } catch (IllegalNameException ex) {
618 text.setBorder(BorderFactory.createLineBorder(Color.red, 1)); 620 text.setBorder(BorderFactory.createLineBorder(Color.red, 1));
619 text.setToolTipText(ex.getReason()); 621 text.setToolTipText(ex.getReason());
@@ -737,13 +739,13 @@ public class Gui {
737 739
738 public void showDiscardDiag(Function<Integer, Void> callback, String... options) { 740 public void showDiscardDiag(Function<Integer, Void> callback, String... options) {
739 int response = JOptionPane.showOptionDialog(this.frame, "Your mappings have not been saved yet. Do you want to save?", "Save your changes?", JOptionPane.YES_NO_CANCEL_OPTION, 741 int response = JOptionPane.showOptionDialog(this.frame, "Your mappings have not been saved yet. Do you want to save?", "Save your changes?", JOptionPane.YES_NO_CANCEL_OPTION,
740 JOptionPane.QUESTION_MESSAGE, null, options, options[2]); 742 JOptionPane.QUESTION_MESSAGE, null, options, options[2]);
741 callback.apply(response); 743 callback.apply(response);
742 } 744 }
743 745
744 public void saveMapping() throws IOException { 746 public void saveMapping() throws IOException {
745 if (this.enigmaMappingsFileChooser.getSelectedFile() != null || this.enigmaMappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION) 747 if (this.enigmaMappingsFileChooser.getSelectedFile() != null || this.enigmaMappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION)
746 this.controller.saveMappings(this.enigmaMappingsFileChooser.getSelectedFile()); 748 this.controller.saveMappings(this.enigmaMappingsFileChooser.getSelectedFile().toPath());
747 } 749 }
748 750
749 public void close() { 751 public void close() {
@@ -782,7 +784,7 @@ public class Gui {
782 DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i); 784 DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i);
783 ClassEntry prevDataChild = (ClassEntry) childNode.getUserObject(); 785 ClassEntry prevDataChild = (ClassEntry) childNode.getUserObject();
784 ClassEntry dataChild = new ClassEntry(data + "/" + prevDataChild.getSimpleName()); 786 ClassEntry dataChild = new ClassEntry(data + "/" + prevDataChild.getSimpleName());
785 this.controller.rename(new EntryReference<>(prevDataChild, prevDataChild.getName()), dataChild.getName(), false, i + 1 == node.getChildCount()); 787 this.controller.rename(new EntryReference<>(prevDataChild, prevDataChild.getFullName()), dataChild.getFullName(), false);
786 childNode.setUserObject(dataChild); 788 childNode.setUserObject(dataChild);
787 } 789 }
788 node.setUserObject(data); 790 node.setUserObject(data);
@@ -791,19 +793,19 @@ public class Gui {
791 } 793 }
792 // class rename 794 // class rename
793 else if (data instanceof ClassEntry) 795 else if (data instanceof ClassEntry)
794 this.controller.rename(new EntryReference<>((ClassEntry) prevData, ((ClassEntry) prevData).getName()), ((ClassEntry) data).getName(), false, true); 796 this.controller.rename(new EntryReference<>((ClassEntry) prevData, ((ClassEntry) prevData).getFullName()), ((ClassEntry) data).getFullName(), false);
795 } 797 }
796 798
797 public void moveClassTree(EntryReference<Entry, Entry> deobfReference, String newName) { 799 public void moveClassTree(EntryReference<Entry<?>, Entry<?>> deobfReference, String newName) {
798 String oldEntry = deobfReference.entry.getOwnerClassEntry().getPackageName(); 800 String oldEntry = deobfReference.entry.getContainingClass().getPackageName();
799 String newEntry = new ClassEntry(newName).getPackageName(); 801 String newEntry = new ClassEntry(newName).getPackageName();
800 moveClassTree(deobfReference, newName, oldEntry == null, 802 moveClassTree(deobfReference, newName, oldEntry == null,
801 newEntry == null); 803 newEntry == null);
802 } 804 }
803 805
804 // TODO: getExpansionState will *not* actually update itself based on name changes! 806 // TODO: getExpansionState will *not* actually update itself based on name changes!
805 public void moveClassTree(EntryReference<Entry, Entry> deobfReference, String newName, boolean isOldOb, boolean isNewOb) { 807 public void moveClassTree(EntryReference<Entry<?>, Entry<?>> deobfReference, String newName, boolean isOldOb, boolean isNewOb) {
806 ClassEntry oldEntry = deobfReference.entry.getOwnerClassEntry(); 808 ClassEntry oldEntry = deobfReference.entry.getContainingClass();
807 ClassEntry newEntry = new ClassEntry(newName); 809 ClassEntry newEntry = new ClassEntry(newName);
808 810
809 // Ob -> deob 811 // Ob -> deob
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java
index 69aefe5..06cb33e 100644
--- a/src/main/java/cuchaz/enigma/gui/GuiController.java
+++ b/src/main/java/cuchaz/enigma/gui/GuiController.java
@@ -20,19 +20,25 @@ import cuchaz.enigma.analysis.*;
20import cuchaz.enigma.api.EnigmaPlugin; 20import cuchaz.enigma.api.EnigmaPlugin;
21import cuchaz.enigma.config.Config; 21import cuchaz.enigma.config.Config;
22import cuchaz.enigma.gui.dialog.ProgressDialog; 22import cuchaz.enigma.gui.dialog.ProgressDialog;
23import cuchaz.enigma.mapping.*;
24import cuchaz.enigma.mapping.entry.ClassEntry;
25import cuchaz.enigma.mapping.entry.Entry;
26import cuchaz.enigma.mapping.entry.FieldEntry;
27import cuchaz.enigma.mapping.entry.MethodEntry;
28import cuchaz.enigma.throwables.MappingParseException; 23import cuchaz.enigma.throwables.MappingParseException;
24import cuchaz.enigma.translation.Translator;
25import cuchaz.enigma.translation.mapping.*;
26import cuchaz.enigma.translation.mapping.serde.MappingFormat;
27import cuchaz.enigma.translation.mapping.tree.EntryTree;
28import cuchaz.enigma.translation.representation.entry.ClassEntry;
29import cuchaz.enigma.translation.representation.entry.Entry;
30import cuchaz.enigma.translation.representation.entry.FieldEntry;
31import cuchaz.enigma.translation.representation.entry.MethodEntry;
29import cuchaz.enigma.utils.ReadableToken; 32import cuchaz.enigma.utils.ReadableToken;
30 33
34import javax.annotation.Nullable;
31import java.awt.event.ItemEvent; 35import java.awt.event.ItemEvent;
32import java.io.File; 36import java.io.File;
33import java.io.IOException; 37import java.io.IOException;
38import java.nio.file.Path;
34import java.util.*; 39import java.util.*;
35import java.util.jar.JarFile; 40import java.util.jar.JarFile;
41import java.util.stream.Collectors;
36 42
37public class GuiController { 43public class GuiController {
38 44
@@ -40,27 +46,26 @@ public class GuiController {
40 private Gui gui; 46 private Gui gui;
41 private SourceIndex index; 47 private SourceIndex index;
42 private ClassEntry currentObfClass; 48 private ClassEntry currentObfClass;
43 private boolean isDirty; 49 private Deque<EntryReference<Entry<?>, Entry<?>>> referenceStack;
44 private Deque<EntryReference<Entry, Entry>> referenceStack; 50
51 private Path loadedMappingPath;
52 private MappingFormat loadedMappingFormat;
45 53
46 public GuiController(Gui gui) { 54 public GuiController(Gui gui) {
47 this.gui = gui; 55 this.gui = gui;
48 this.deobfuscator = null; 56 this.deobfuscator = null;
49 this.index = null; 57 this.index = null;
50 this.currentObfClass = null; 58 this.currentObfClass = null;
51 this.isDirty = false;
52 this.referenceStack = Queues.newArrayDeque(); 59 this.referenceStack = Queues.newArrayDeque();
53 } 60 }
54 61
55 public boolean isDirty() { 62 public boolean isDirty() {
56 return this.isDirty; 63 return deobfuscator.getMapper().isDirty();
57 } 64 }
58 65
59 public void openJar(final JarFile jar) throws IOException { 66 public void openJar(final JarFile jar) throws IOException {
60 this.gui.onStartOpenJar("Loading JAR..."); 67 this.gui.onStartOpenJar("Loading JAR...");
61 this.deobfuscator = new Deobfuscator(jar, (msg) -> { 68 this.deobfuscator = new Deobfuscator(jar, this.gui::onStartOpenJar);
62 this.gui.onStartOpenJar(msg);
63 });
64 this.gui.onFinishOpenJar(jar.getName()); 69 this.gui.onFinishOpenJar(jar.getName());
65 refreshClasses(); 70 refreshClasses();
66 } 71 }
@@ -70,43 +75,37 @@ public class GuiController {
70 this.gui.onCloseJar(); 75 this.gui.onCloseJar();
71 } 76 }
72 77
73 public void openEnigmaMappings(File file) throws IOException, MappingParseException { 78 public void openMappings(MappingFormat format, Path path) throws IOException, MappingParseException {
74 this.deobfuscator.setMappings(new MappingsEnigmaReader().read(file)); 79 EntryTree<EntryMapping> mappings = format.read(path);
75 this.isDirty = false; 80 deobfuscator.setMappings(mappings);
76 this.gui.setMappingsFile(file); 81
82 gui.setMappingsFile(path);
83 loadedMappingFormat = format;
84
77 refreshClasses(); 85 refreshClasses();
78 refreshCurrentClass(); 86 refreshCurrentClass();
79 } 87 }
80 88
81 public void openTinyMappings(File file) throws IOException, MappingParseException { 89 public void saveMappings(Path path) {
82 this.deobfuscator.setMappings(new MappingsTinyReader().read(file)); 90 saveMappings(loadedMappingFormat, path);
83 this.isDirty = false;
84 this.gui.setMappingsFile(file);
85 refreshClasses();
86 refreshCurrentClass();
87 } 91 }
88 92
89 public void saveMappings(File file) throws IOException { 93 public void saveMappings(MappingFormat format, Path path) {
90 Mappings mappings = this.deobfuscator.getMappings(); 94 EntryRemapper mapper = deobfuscator.getMapper();
91 switch (mappings.getOriginMappingFormat()) {
92 case SRG_FILE:
93 saveSRGMappings(file);
94 break;
95 default:
96 saveEnigmaMappings(file, Mappings.FormatType.ENIGMA_FILE != mappings.getOriginMappingFormat());
97 break;
98 }
99 95
100 } 96 MappingDelta delta = mapper.takeMappingDelta();
97 boolean saveAll = !path.equals(loadedMappingPath);
101 98
102 public void saveEnigmaMappings(File file, boolean isDirectoryFormat) throws IOException { 99 ProgressDialog.runInThread(this.gui.getFrame(), progress -> {
103 this.deobfuscator.getMappings().saveEnigmaMappings(file, isDirectoryFormat); 100 if (saveAll) {
104 this.isDirty = false; 101 format.write(mapper.getObfToDeobf(), path, progress);
105 } 102 } else {
103 format.write(mapper.getObfToDeobf(), delta, path, progress);
104 }
105 });
106 106
107 public void saveSRGMappings(File file) throws IOException { 107 loadedMappingFormat = format;
108 this.deobfuscator.getMappings().saveSRGMappings(file); 108 loadedMappingPath = path;
109 this.isDirty = false;
110 } 109 }
111 110
112 public void closeMappings() { 111 public void closeMappings() {
@@ -116,11 +115,6 @@ public class GuiController {
116 refreshCurrentClass(); 115 refreshCurrentClass();
117 } 116 }
118 117
119 public void rebuildMethodNames() {
120 ProgressDialog.runInThread(this.gui.getFrame(), progress -> this.deobfuscator.rebuildMethodNames(progress));
121 this.isDirty = true;
122 }
123
124 public void exportSource(final File dirOut) { 118 public void exportSource(final File dirOut) {
125 ProgressDialog.runInThread(this.gui.getFrame(), progress -> this.deobfuscator.writeSources(dirOut, progress)); 119 ProgressDialog.runInThread(this.gui.getFrame(), progress -> this.deobfuscator.writeSources(dirOut, progress));
126 } 120 }
@@ -136,7 +130,8 @@ public class GuiController {
136 return this.index.getReferenceToken(pos); 130 return this.index.getReferenceToken(pos);
137 } 131 }
138 132
139 public EntryReference<Entry, Entry> getDeobfReference(Token token) { 133 @Nullable
134 public EntryReference<Entry<?>, Entry<?>> getDeobfReference(Token token) {
140 if (this.index == null) { 135 if (this.index == null) {
141 return null; 136 return null;
142 } 137 }
@@ -148,44 +143,52 @@ public class GuiController {
148 return null; 143 return null;
149 } 144 }
150 return new ReadableToken( 145 return new ReadableToken(
151 this.index.getLineNumber(token.start), 146 this.index.getLineNumber(token.start),
152 this.index.getColumnNumber(token.start), 147 this.index.getColumnNumber(token.start),
153 this.index.getColumnNumber(token.end) 148 this.index.getColumnNumber(token.end)
154 ); 149 );
155 } 150 }
156 151
157 public boolean entryHasDeobfuscatedName(Entry deobfEntry) { 152 public boolean entryHasDeobfuscatedName(Entry<?> deobfEntry) {
158 return this.deobfuscator.hasDeobfuscatedName(this.deobfuscator.obfuscateEntry(deobfEntry)); 153 EntryResolver resolver = this.deobfuscator.getMapper().getDeobfResolver();
154 Entry<?> resolvedEntry = resolver.resolveFirstEntry(deobfEntry, ResolutionStrategy.RESOLVE_ROOT);
155 return this.deobfuscator.hasDeobfuscatedName(this.deobfuscator.getMapper().obfuscate(resolvedEntry));
159 } 156 }
160 157
161 public boolean entryIsInJar(Entry deobfEntry) { 158 public boolean entryIsInJar(Entry<?> deobfEntry) {
162 return this.deobfuscator.isObfuscatedIdentifier(this.deobfuscator.obfuscateEntry(deobfEntry)); 159 if (deobfEntry == null) return false;
160 return this.deobfuscator.isObfuscatedIdentifier(this.deobfuscator.getMapper().obfuscate(deobfEntry));
163 } 161 }
164 162
165 public boolean referenceIsRenameable(EntryReference<Entry, Entry> deobfReference) { 163 public boolean referenceIsRenameable(EntryReference<Entry<?>, Entry<?>> deobfReference) {
166 return this.deobfuscator.isRenameable(this.deobfuscator.obfuscateReference(deobfReference)); 164 if (deobfReference == null) return false;
165 return this.deobfuscator.isRenameable(this.deobfuscator.getMapper().obfuscate(deobfReference));
167 } 166 }
168 167
169 public ClassInheritanceTreeNode getClassInheritance(ClassEntry deobfClassEntry) { 168 public ClassInheritanceTreeNode getClassInheritance(ClassEntry deobfClassEntry) {
170 ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry); 169 ClassEntry obfClassEntry = this.deobfuscator.getMapper().obfuscate(deobfClassEntry);
171 ClassInheritanceTreeNode rootNode = this.deobfuscator.getJarIndex().getClassInheritance(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry); 170 Translator translator = this.deobfuscator.getMapper().getDeobfuscator();
171 ClassInheritanceTreeNode rootNode = this.deobfuscator.getIndexTreeBuilder().buildClassInheritance(translator, obfClassEntry);
172 return ClassInheritanceTreeNode.findNode(rootNode, obfClassEntry); 172 return ClassInheritanceTreeNode.findNode(rootNode, obfClassEntry);
173 } 173 }
174 174
175 public ClassImplementationsTreeNode getClassImplementations(ClassEntry deobfClassEntry) { 175 public ClassImplementationsTreeNode getClassImplementations(ClassEntry deobfClassEntry) {
176 ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry); 176 ClassEntry obfClassEntry = this.deobfuscator.getMapper().obfuscate(deobfClassEntry);
177 return this.deobfuscator.getJarIndex().getClassImplementations(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry); 177 Translator translator = this.deobfuscator.getMapper().getDeobfuscator();
178 return this.deobfuscator.getIndexTreeBuilder().buildClassImplementations(translator, obfClassEntry);
178 } 179 }
179 180
180 public MethodInheritanceTreeNode getMethodInheritance(MethodEntry deobfMethodEntry) { 181 public MethodInheritanceTreeNode getMethodInheritance(MethodEntry deobfMethodEntry) {
181 MethodEntry obfMethodEntry = this.deobfuscator.obfuscateEntry(deobfMethodEntry); 182 MethodEntry obfMethodEntry = this.deobfuscator.getMapper().obfuscate(deobfMethodEntry);
182 MethodInheritanceTreeNode rootNode = this.deobfuscator.getJarIndex().getMethodInheritance(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfMethodEntry); 183 Translator translator = this.deobfuscator.getMapper().getDeobfuscator();
184 MethodInheritanceTreeNode rootNode = this.deobfuscator.getIndexTreeBuilder().buildMethodInheritance(translator, obfMethodEntry);
183 return MethodInheritanceTreeNode.findNode(rootNode, obfMethodEntry); 185 return MethodInheritanceTreeNode.findNode(rootNode, obfMethodEntry);
184 } 186 }
185 187
186 public MethodImplementationsTreeNode getMethodImplementations(MethodEntry deobfMethodEntry) { 188 public MethodImplementationsTreeNode getMethodImplementations(MethodEntry deobfMethodEntry) {
187 MethodEntry obfMethodEntry = this.deobfuscator.obfuscateEntry(deobfMethodEntry); 189 MethodEntry obfMethodEntry = this.deobfuscator.getMapper().obfuscate(deobfMethodEntry);
188 List<MethodImplementationsTreeNode> rootNodes = this.deobfuscator.getJarIndex().getMethodImplementations(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfMethodEntry); 190 Translator translator = this.deobfuscator.getMapper().getDeobfuscator();
191 List<MethodImplementationsTreeNode> rootNodes = this.deobfuscator.getIndexTreeBuilder().buildMethodImplementations(translator, obfMethodEntry);
189 if (rootNodes.isEmpty()) { 192 if (rootNodes.isEmpty()) {
190 return null; 193 return null;
191 } 194 }
@@ -196,34 +199,32 @@ public class GuiController {
196 } 199 }
197 200
198 public ClassReferenceTreeNode getClassReferences(ClassEntry deobfClassEntry) { 201 public ClassReferenceTreeNode getClassReferences(ClassEntry deobfClassEntry) {
199 ClassEntry obfClassEntry = this.deobfuscator.obfuscateEntry(deobfClassEntry); 202 ClassEntry obfClassEntry = this.deobfuscator.getMapper().obfuscate(deobfClassEntry);
200 ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfClassEntry); 203 Translator deobfuscator = this.deobfuscator.getMapper().getDeobfuscator();
204 ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(deobfuscator, obfClassEntry);
201 rootNode.load(this.deobfuscator.getJarIndex(), true); 205 rootNode.load(this.deobfuscator.getJarIndex(), true);
202 return rootNode; 206 return rootNode;
203 } 207 }
204 208
205 public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) { 209 public FieldReferenceTreeNode getFieldReferences(FieldEntry deobfFieldEntry) {
206 FieldEntry obfFieldEntry = this.deobfuscator.obfuscateEntry(deobfFieldEntry); 210 FieldEntry obfFieldEntry = this.deobfuscator.getMapper().obfuscate(deobfFieldEntry);
207 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfFieldEntry); 211 Translator translator = this.deobfuscator.getMapper().getDeobfuscator();
212 FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(translator, obfFieldEntry);
208 rootNode.load(this.deobfuscator.getJarIndex(), true); 213 rootNode.load(this.deobfuscator.getJarIndex(), true);
209 return rootNode; 214 return rootNode;
210 } 215 }
211 216
212 public MethodReferenceTreeNode getMethodReferences(MethodEntry deobfMethodEntry, boolean recursive) { 217 public MethodReferenceTreeNode getMethodReferences(MethodEntry deobfMethodEntry, boolean recursive) {
213 MethodEntry obfMethodEntry = this.deobfuscator.obfuscateEntry(deobfMethodEntry); 218 MethodEntry obfMethodEntry = this.deobfuscator.getMapper().obfuscate(deobfMethodEntry);
214 MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(this.deobfuscator.getTranslator(TranslationDirection.DEOBFUSCATING), obfMethodEntry); 219 Translator translator = this.deobfuscator.getMapper().getDeobfuscator();
220 MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(translator, obfMethodEntry);
215 rootNode.load(this.deobfuscator.getJarIndex(), true, recursive); 221 rootNode.load(this.deobfuscator.getJarIndex(), true, recursive);
216 return rootNode; 222 return rootNode;
217 } 223 }
218 224
219 public void rename(EntryReference<Entry, Entry> deobfReference, String newName) { 225 public void rename(EntryReference<Entry<?>, Entry<?>> deobfReference, String newName, boolean refreshClassTree) {
220 rename(deobfReference, newName, true, true); 226 EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference);
221 } 227 this.deobfuscator.rename(obfReference.getNameableEntry(), newName);
222
223 public void rename(EntryReference<Entry, Entry> deobfReference, String newName, boolean refreshClassTree, boolean clearTranslationCache) {
224 EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference);
225 this.deobfuscator.rename(obfReference.getNameableEntry(), newName, clearTranslationCache);
226 this.isDirty = true;
227 228
228 if (refreshClassTree && deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass()) 229 if (refreshClassTree && deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass())
229 this.gui.moveClassTree(deobfReference, newName); 230 this.gui.moveClassTree(deobfReference, newName);
@@ -231,39 +232,37 @@ public class GuiController {
231 232
232 } 233 }
233 234
234 public void removeMapping(EntryReference<Entry, Entry> deobfReference) { 235 public void removeMapping(EntryReference<Entry<?>, Entry<?>> deobfReference) {
235 EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); 236 EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference);
236 this.deobfuscator.removeMapping(obfReference.getNameableEntry()); 237 this.deobfuscator.removeMapping(obfReference.getNameableEntry());
237 this.isDirty = true;
238 if (deobfReference.entry instanceof ClassEntry) 238 if (deobfReference.entry instanceof ClassEntry)
239 this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), false, true); 239 this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), false, true);
240 refreshCurrentClass(obfReference); 240 refreshCurrentClass(obfReference);
241 } 241 }
242 242
243 public void markAsDeobfuscated(EntryReference<Entry, Entry> deobfReference) { 243 public void markAsDeobfuscated(EntryReference<Entry<?>, Entry<?>> deobfReference) {
244 EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); 244 EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference);
245 this.deobfuscator.markAsDeobfuscated(obfReference.getNameableEntry()); 245 this.deobfuscator.markAsDeobfuscated(obfReference.getNameableEntry());
246 this.isDirty = true;
247 if (deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass()) 246 if (deobfReference.entry instanceof ClassEntry && !((ClassEntry) deobfReference.entry).isInnerClass())
248 this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), true, false); 247 this.gui.moveClassTree(deobfReference, obfReference.entry.getName(), true, false);
249 refreshCurrentClass(obfReference); 248 refreshCurrentClass(obfReference);
250 } 249 }
251 250
252 public void openDeclaration(Entry deobfEntry) { 251 public void openDeclaration(Entry<?> deobfEntry) {
253 if (deobfEntry == null) { 252 if (deobfEntry == null) {
254 throw new IllegalArgumentException("Entry cannot be null!"); 253 throw new IllegalArgumentException("Entry cannot be null!");
255 } 254 }
256 openReference(new EntryReference<>(deobfEntry, deobfEntry.getName())); 255 openReference(new EntryReference<>(deobfEntry, deobfEntry.getName()));
257 } 256 }
258 257
259 public void openReference(EntryReference<Entry, Entry> deobfReference) { 258 public void openReference(EntryReference<Entry<?>, Entry<?>> deobfReference) {
260 if (deobfReference == null) { 259 if (deobfReference == null) {
261 throw new IllegalArgumentException("Reference cannot be null!"); 260 throw new IllegalArgumentException("Reference cannot be null!");
262 } 261 }
263 262
264 // get the reference target class 263 // get the reference target class
265 EntryReference<Entry, Entry> obfReference = this.deobfuscator.obfuscateReference(deobfReference); 264 EntryReference<Entry<?>, Entry<?>> obfReference = this.deobfuscator.getMapper().obfuscate(deobfReference);
266 ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOutermostClassEntry(); 265 ClassEntry obfClassEntry = obfReference.getLocationClassEntry();
267 if (!this.deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { 266 if (!this.deobfuscator.isObfuscatedIdentifier(obfClassEntry)) {
268 throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); 267 throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!");
269 } 268 }
@@ -276,24 +275,30 @@ public class GuiController {
276 } 275 }
277 } 276 }
278 277
279 private void showReference(EntryReference<Entry, Entry> obfReference) { 278 private void showReference(EntryReference<Entry<?>, Entry<?>> obfReference) {
280 EntryReference<Entry, Entry> deobfReference = this.deobfuscator.deobfuscateReference(obfReference); 279 EntryRemapper mapper = this.deobfuscator.getMapper();
281 Collection<Token> tokens = this.index.getReferenceTokens(deobfReference); 280
281 Collection<Token> tokens = mapper.getObfResolver().resolveReference(obfReference, ResolutionStrategy.RESOLVE_ROOT)
282 .stream()
283 .map(mapper::deobfuscate)
284 .flatMap(reference -> index.getReferenceTokens(reference).stream())
285 .collect(Collectors.toList());
286
282 if (tokens.isEmpty()) { 287 if (tokens.isEmpty()) {
283 // DEBUG 288 // DEBUG
284 System.err.println(String.format("WARNING: no tokens found for %s in %s", deobfReference, this.currentObfClass)); 289 System.err.println(String.format("WARNING: no tokens found for %s in %s", tokens, this.currentObfClass));
285 } else { 290 } else {
286 this.gui.showTokens(tokens); 291 this.gui.showTokens(tokens);
287 } 292 }
288 } 293 }
289 294
290 public void savePreviousReference(EntryReference<Entry, Entry> deobfReference) { 295 public void savePreviousReference(EntryReference<Entry<?>, Entry<?>> deobfReference) {
291 this.referenceStack.push(this.deobfuscator.obfuscateReference(deobfReference)); 296 this.referenceStack.push(this.deobfuscator.getMapper().obfuscate(deobfReference));
292 } 297 }
293 298
294 public void openPreviousReference() { 299 public void openPreviousReference() {
295 if (hasPreviousLocation()) { 300 if (hasPreviousLocation()) {
296 openReference(this.deobfuscator.deobfuscateReference(this.referenceStack.pop())); 301 openReference(this.deobfuscator.getMapper().deobfuscate(this.referenceStack.pop()));
297 } 302 }
298 } 303 }
299 304
@@ -313,13 +318,13 @@ public class GuiController {
313 refreshCurrentClass(null); 318 refreshCurrentClass(null);
314 } 319 }
315 320
316 private void refreshCurrentClass(EntryReference<Entry, Entry> obfReference) { 321 private void refreshCurrentClass(EntryReference<Entry<?>, Entry<?>> obfReference) {
317 if (this.currentObfClass != null) { 322 if (this.currentObfClass != null) {
318 deobfuscate(this.currentObfClass, obfReference); 323 deobfuscate(this.currentObfClass, obfReference);
319 } 324 }
320 } 325 }
321 326
322 private void deobfuscate(final ClassEntry classEntry, final EntryReference<Entry, Entry> obfReference) { 327 private void deobfuscate(final ClassEntry classEntry, final EntryReference<Entry<?>, Entry<?>> obfReference) {
323 328
324 this.gui.setSource("(deobfuscating...)"); 329 this.gui.setSource("(deobfuscating...)");
325 330
@@ -327,7 +332,7 @@ public class GuiController {
327 new Thread(() -> 332 new Thread(() ->
328 { 333 {
329 // decompile,deobfuscate the bytecode 334 // decompile,deobfuscate the bytecode
330 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getClassName()); 335 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getFullName());
331 if (sourceTree == null) { 336 if (sourceTree == null) {
332 // decompilation of this class is not supported 337 // decompilation of this class is not supported
333 gui.setSource("Unable to find class: " + classEntry); 338 gui.setSource("Unable to find class: " + classEntry);
@@ -349,17 +354,18 @@ public class GuiController {
349 boolean remapped = false; 354 boolean remapped = false;
350 355
351 for (Token inToken : index.referenceTokens()) { 356 for (Token inToken : index.referenceTokens()) {
352 EntryReference<Entry, Entry> reference = index.getDeobfReference(inToken);
353 Token token = inToken.move(offset); 357 Token token = inToken.move(offset);
354 358
359 EntryReference<Entry<?>, Entry<?>> reference = index.getDeobfReference(inToken);
355 if (referenceIsRenameable(reference)) { 360 if (referenceIsRenameable(reference)) {
356 boolean added = false; 361 boolean added = false;
357 362
358 if (!entryHasDeobfuscatedName(reference.getNameableEntry())) { 363 if (!entryHasDeobfuscatedName(reference.getNameableEntry())) {
359 Entry obfEntry = deobfuscator.obfuscateEntry(reference.getNameableEntry()); 364 Entry<?> obfEntry = deobfuscator.getMapper().obfuscate(reference.getNameableEntry());
360 if (obfEntry instanceof FieldEntry) { 365 if (obfEntry instanceof FieldEntry) {
361 for (EnigmaPlugin plugin : deobfuscator.getPlugins()) { 366 for (EnigmaPlugin plugin : deobfuscator.getPlugins()) {
362 String proposal = plugin.proposeFieldName(obfEntry.getClassName(), obfEntry.getName(), ((FieldEntry) obfEntry).getDesc().toString()); 367 String owner = obfEntry.getContainingClass().getFullName();
368 String proposal = plugin.proposeFieldName(owner, obfEntry.getName(), ((FieldEntry) obfEntry).getDesc().toString());
363 if (proposal != null) { 369 if (proposal != null) {
364 proposedTokens.add(token); 370 proposedTokens.add(token);
365 offset += token.getRenameOffset(proposal); 371 offset += token.getRenameOffset(proposal);
@@ -411,8 +417,7 @@ public class GuiController {
411 417
412 public void modifierChange(ItemEvent event) { 418 public void modifierChange(ItemEvent event) {
413 if (event.getStateChange() == ItemEvent.SELECTED) { 419 if (event.getStateChange() == ItemEvent.SELECTED) {
414 deobfuscator.changeModifier(gui.reference.entry, (Mappings.EntryModifier) event.getItem()); 420 deobfuscator.changeModifier(gui.reference.entry, (AccessModifier) event.getItem());
415 this.isDirty = true;
416 refreshCurrentClass(); 421 refreshCurrentClass();
417 } 422 }
418 } 423 }
diff --git a/src/main/java/cuchaz/enigma/gui/GuiTricks.java b/src/main/java/cuchaz/enigma/gui/GuiTricks.java
deleted file mode 100644
index 9208455..0000000
--- a/src/main/java/cuchaz/enigma/gui/GuiTricks.java
+++ /dev/null
@@ -1,42 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.gui;
13
14import javax.swing.*;
15import java.awt.*;
16import java.awt.event.ActionListener;
17
18public class GuiTricks {
19
20 public static JLabel unboldLabel(JLabel label) {
21 Font font = label.getFont();
22 label.setFont(font.deriveFont(font.getStyle() & ~Font.BOLD));
23 return label;
24 }
25
26 public static void deactivateButton(JButton button) {
27 button.setEnabled(false);
28 button.setText("");
29 for (ActionListener listener : button.getActionListeners()) {
30 button.removeActionListener(listener);
31 }
32 }
33
34 public static void activateButton(JButton button, String text, ActionListener newListener) {
35 button.setText(text);
36 button.setEnabled(true);
37 for (ActionListener listener : button.getActionListeners()) {
38 button.removeActionListener(listener);
39 }
40 button.addActionListener(newListener);
41 }
42}
diff --git a/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java b/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java
deleted file mode 100644
index 34ec26e..0000000
--- a/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java
+++ /dev/null
@@ -1,44 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.gui;
13
14import cuchaz.enigma.mapping.entry.ClassEntry;
15
16public class ScoredClassEntry extends ClassEntry {
17
18 private static final long serialVersionUID = -8798725308554217105L;
19
20 private float score;
21
22 public ScoredClassEntry(ClassEntry other, float score) {
23 super(other);
24 this.score = score;
25 }
26
27 public float getScore() {
28 return score;
29 }
30
31 @Override
32 public int hashCode() {
33 return Float.hashCode(score) + super.hashCode();
34 }
35
36 @Override
37 public boolean equals(Object other) {
38 return super.equals(other) && other instanceof ScoredClassEntry && equals((ScoredClassEntry) other);
39 }
40
41 public boolean equals(ScoredClassEntry other) {
42 return other != null && Float.compare(score, other.score) == 0;
43 }
44}
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
index 5f04833..84fe7c8 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
@@ -12,7 +12,7 @@
12package cuchaz.enigma.gui.dialog; 12package cuchaz.enigma.gui.dialog;
13 13
14import cuchaz.enigma.Constants; 14import cuchaz.enigma.Constants;
15import cuchaz.enigma.Deobfuscator.ProgressListener; 15import cuchaz.enigma.ProgressListener;
16import cuchaz.enigma.utils.Utils; 16import cuchaz.enigma.utils.Utils;
17 17
18import javax.swing.*; 18import javax.swing.*;
@@ -81,7 +81,7 @@ public class ProgressDialog implements ProgressListener, AutoCloseable {
81 } 81 }
82 82
83 @Override 83 @Override
84 public void onProgress(int numDone, String message) { 84 public void step(int numDone, String message) {
85 this.labelText.setText(message); 85 this.labelText.setText(message);
86 this.progress.setValue(numDone); 86 this.progress.setValue(numDone);
87 87
diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
index 609aecb..f4f0277 100644
--- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
+++ b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
@@ -5,6 +5,7 @@ import cuchaz.enigma.config.Themes;
5import cuchaz.enigma.gui.Gui; 5import cuchaz.enigma.gui.Gui;
6import cuchaz.enigma.gui.dialog.AboutDialog; 6import cuchaz.enigma.gui.dialog.AboutDialog;
7import cuchaz.enigma.throwables.MappingParseException; 7import cuchaz.enigma.throwables.MappingParseException;
8import cuchaz.enigma.translation.mapping.serde.MappingFormat;
8 9
9import javax.swing.*; 10import javax.swing.*;
10import java.awt.event.InputEvent; 11import java.awt.event.InputEvent;
@@ -23,7 +24,6 @@ public class MenuBar extends JMenuBar {
23 public final JMenuItem saveMappingEnigmaDirectoryMenu; 24 public final JMenuItem saveMappingEnigmaDirectoryMenu;
24 public final JMenuItem saveMappingsSrgMenu; 25 public final JMenuItem saveMappingsSrgMenu;
25 public final JMenuItem closeMappingsMenu; 26 public final JMenuItem closeMappingsMenu;
26 public final JMenuItem rebuildMethodNamesMenu;
27 public final JMenuItem exportSourceMenu; 27 public final JMenuItem exportSourceMenu;
28 public final JMenuItem exportJarMenu; 28 public final JMenuItem exportJarMenu;
29 private final Gui gui; 29 private final Gui gui;
@@ -68,7 +68,9 @@ public class MenuBar extends JMenuBar {
68 item.addActionListener(event -> { 68 item.addActionListener(event -> {
69 if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 69 if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
70 try { 70 try {
71 this.gui.getController().openEnigmaMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile()); 71 File selectedFile = this.gui.enigmaMappingsFileChooser.getSelectedFile();
72 MappingFormat format = selectedFile.isDirectory() ? MappingFormat.ENIGMA_DIRECTORY : MappingFormat.ENIGMA_FILE;
73 this.gui.getController().openMappings(format, selectedFile.toPath());
72 } catch (IOException ex) { 74 } catch (IOException ex) {
73 throw new Error(ex); 75 throw new Error(ex);
74 } catch (MappingParseException ex) { 76 } catch (MappingParseException ex) {
@@ -85,7 +87,7 @@ public class MenuBar extends JMenuBar {
85 File file = new File(this.gui.tinyMappingsFileChooser.getDirectory() + File.separator + this.gui.tinyMappingsFileChooser.getFile()); 87 File file = new File(this.gui.tinyMappingsFileChooser.getDirectory() + File.separator + this.gui.tinyMappingsFileChooser.getFile());
86 if (file.exists()) { 88 if (file.exists()) {
87 try { 89 try {
88 this.gui.getController().openTinyMappings(file); 90 this.gui.getController().openMappings(MappingFormat.TINY_FILE, file.toPath());
89 } catch (IOException ex) { 91 } catch (IOException ex) {
90 throw new Error(ex); 92 throw new Error(ex);
91 } catch (MappingParseException ex) { 93 } catch (MappingParseException ex) {
@@ -99,11 +101,7 @@ public class MenuBar extends JMenuBar {
99 JMenuItem item = new JMenuItem("Save Mappings"); 101 JMenuItem item = new JMenuItem("Save Mappings");
100 menu.add(item); 102 menu.add(item);
101 item.addActionListener(event -> { 103 item.addActionListener(event -> {
102 try { 104 this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath());
103 this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile());
104 } catch (IOException ex) {
105 throw new Error(ex);
106 }
107 }); 105 });
108 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); 106 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
109 this.saveMappingsMenu = item; 107 this.saveMappingsMenu = item;
@@ -116,12 +114,8 @@ public class MenuBar extends JMenuBar {
116 item.addActionListener(event -> { 114 item.addActionListener(event -> {
117 // TODO: Use a specific file chooser for it 115 // TODO: Use a specific file chooser for it
118 if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 116 if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
119 try { 117 this.gui.getController().saveMappings(MappingFormat.ENIGMA_FILE, this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath());
120 this.gui.getController().saveEnigmaMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile(), false); 118 this.saveMappingsMenu.setEnabled(true);
121 this.saveMappingsMenu.setEnabled(true);
122 } catch (IOException ex) {
123 throw new Error(ex);
124 }
125 } 119 }
126 }); 120 });
127 this.saveMappingEnigmaFileMenu = item; 121 this.saveMappingEnigmaFileMenu = item;
@@ -132,12 +126,8 @@ public class MenuBar extends JMenuBar {
132 item.addActionListener(event -> { 126 item.addActionListener(event -> {
133 // TODO: Use a specific file chooser for it 127 // TODO: Use a specific file chooser for it
134 if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 128 if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
135 try { 129 this.gui.getController().saveMappings(MappingFormat.ENIGMA_DIRECTORY, this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath());
136 this.gui.getController().saveEnigmaMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile(), true); 130 this.saveMappingsMenu.setEnabled(true);
137 this.saveMappingsMenu.setEnabled(true);
138 } catch (IOException ex) {
139 throw new Error(ex);
140 }
141 } 131 }
142 }); 132 });
143 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); 133 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
@@ -149,12 +139,8 @@ public class MenuBar extends JMenuBar {
149 item.addActionListener(event -> { 139 item.addActionListener(event -> {
150 // TODO: Use a specific file chooser for it 140 // TODO: Use a specific file chooser for it
151 if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 141 if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
152 try { 142 this.gui.getController().saveMappings(MappingFormat.SRG_FILE, this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath());
153 this.gui.getController().saveSRGMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile()); 143 this.saveMappingsMenu.setEnabled(true);
154 this.saveMappingsMenu.setEnabled(true);
155 } catch (IOException ex) {
156 throw new Error(ex);
157 }
158 } 144 }
159 }); 145 });
160 this.saveMappingsSrgMenu = item; 146 this.saveMappingsSrgMenu = item;
@@ -184,13 +170,6 @@ public class MenuBar extends JMenuBar {
184 } 170 }
185 menu.addSeparator(); 171 menu.addSeparator();
186 { 172 {
187 JMenuItem item = new JMenuItem("Rebuild Method Names");
188 menu.add(item);
189 item.addActionListener(event -> this.gui.getController().rebuildMethodNames());
190 this.rebuildMethodNamesMenu = item;
191 }
192 menu.addSeparator();
193 {
194 JMenuItem item = new JMenuItem("Export Source..."); 173 JMenuItem item = new JMenuItem("Export Source...");
195 menu.add(item); 174 menu.add(item);
196 item.addActionListener(event -> { 175 item.addActionListener(event -> {
diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java
index a965a8f..bf6b178 100644
--- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java
+++ b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java
@@ -11,7 +11,7 @@
11 11
12package cuchaz.enigma.gui.node; 12package cuchaz.enigma.gui.node;
13 13
14import cuchaz.enigma.mapping.entry.ClassEntry; 14import cuchaz.enigma.translation.representation.entry.ClassEntry;
15 15
16import javax.swing.tree.DefaultMutableTreeNode; 16import javax.swing.tree.DefaultMutableTreeNode;
17 17
diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java b/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java
index 9eb8f8f..ccdc9f8 100644
--- a/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java
+++ b/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java
@@ -2,7 +2,7 @@ package cuchaz.enigma.gui.panels;
2 2
3import cuchaz.enigma.gui.ClassSelector; 3import cuchaz.enigma.gui.ClassSelector;
4import cuchaz.enigma.gui.Gui; 4import cuchaz.enigma.gui.Gui;
5import cuchaz.enigma.mapping.entry.ClassEntry; 5import cuchaz.enigma.translation.representation.entry.ClassEntry;
6 6
7import javax.swing.*; 7import javax.swing.*;
8import java.awt.*; 8import java.awt.*;
@@ -17,8 +17,8 @@ public class PanelObf extends JPanel {
17 this.gui = gui; 17 this.gui = gui;
18 18
19 Comparator<ClassEntry> obfClassComparator = (a, b) -> { 19 Comparator<ClassEntry> obfClassComparator = (a, b) -> {
20 String aname = a.getName(); 20 String aname = a.getFullName();
21 String bname = b.getName(); 21 String bname = b.getFullName();
22 if (aname.length() != bname.length()) { 22 if (aname.length() != bname.length()) {
23 return aname.length() - bname.length(); 23 return aname.length() - bname.length();
24 } 24 }