summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/gui
diff options
context:
space:
mode:
authorGravatar Thog2017-03-07 21:24:39 +0100
committerGravatar Thog2017-03-07 21:30:02 +0100
commitb4aaff683d78ab92b83f3a7257c33b8e27d1affa (patch)
treef23c9bb0927d83cc7302881266b7df8fd37959c7 /src/main/java/cuchaz/enigma/gui
parentAvoid crash of the matcher when the obf name is invalid (set a deob it using ... (diff)
downloadenigma-fork-b4aaff683d78ab92b83f3a7257c33b8e27d1affa.tar.gz
enigma-fork-b4aaff683d78ab92b83f3a7257c33b8e27d1affa.tar.xz
enigma-fork-b4aaff683d78ab92b83f3a7257c33b8e27d1affa.zip
Drop unix case style and implement hashCode when equals is overrided
Also update Guava to version 21
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui')
-rw-r--r--src/main/java/cuchaz/enigma/gui/BrowserCaret.java1
-rw-r--r--src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java290
-rw-r--r--src/main/java/cuchaz/enigma/gui/ClassSelector.java29
-rw-r--r--src/main/java/cuchaz/enigma/gui/CodeReader.java89
-rw-r--r--src/main/java/cuchaz/enigma/gui/Gui.java318
-rw-r--r--src/main/java/cuchaz/enigma/gui/GuiController.java64
-rw-r--r--src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java281
-rw-r--r--src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java20
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java32
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java16
-rw-r--r--src/main/java/cuchaz/enigma/gui/elements/MenuBar.java20
-rw-r--r--src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java2
-rw-r--r--src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java5
-rw-r--r--src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java5
14 files changed, 568 insertions, 604 deletions
diff --git a/src/main/java/cuchaz/enigma/gui/BrowserCaret.java b/src/main/java/cuchaz/enigma/gui/BrowserCaret.java
index 013778a..bcdff51 100644
--- a/src/main/java/cuchaz/enigma/gui/BrowserCaret.java
+++ b/src/main/java/cuchaz/enigma/gui/BrowserCaret.java
@@ -11,7 +11,6 @@
11package cuchaz.enigma.gui; 11package cuchaz.enigma.gui;
12 12
13import javax.swing.text.DefaultCaret; 13import javax.swing.text.DefaultCaret;
14import javax.swing.text.Highlighter;
15 14
16public class BrowserCaret extends DefaultCaret { 15public class BrowserCaret extends DefaultCaret {
17 16
diff --git a/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java b/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
index edf1e30..dcbe1c5 100644
--- a/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
+++ b/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
@@ -13,19 +13,6 @@ package cuchaz.enigma.gui;
13import com.google.common.collect.BiMap; 13import com.google.common.collect.BiMap;
14import com.google.common.collect.Lists; 14import com.google.common.collect.Lists;
15import com.google.common.collect.Maps; 15import com.google.common.collect.Maps;
16
17import java.awt.BorderLayout;
18import java.awt.Container;
19import java.awt.Dimension;
20import java.awt.FlowLayout;
21import java.awt.event.ActionListener;
22import java.util.Collection;
23import java.util.Collections;
24import java.util.List;
25import java.util.Map;
26
27import javax.swing.*;
28
29import cuchaz.enigma.Constants; 16import cuchaz.enigma.Constants;
30import cuchaz.enigma.Deobfuscator; 17import cuchaz.enigma.Deobfuscator;
31import cuchaz.enigma.convert.*; 18import cuchaz.enigma.convert.*;
@@ -37,6 +24,13 @@ import cuchaz.enigma.mapping.MappingsChecker;
37import cuchaz.enigma.throwables.MappingConflict; 24import cuchaz.enigma.throwables.MappingConflict;
38import de.sciss.syntaxpane.DefaultSyntaxKit; 25import de.sciss.syntaxpane.DefaultSyntaxKit;
39 26
27import javax.swing.*;
28import java.awt.*;
29import java.awt.event.ActionListener;
30import java.util.Collection;
31import java.util.List;
32import java.util.Map;
33
40 34
41public class ClassMatchingGui { 35public class ClassMatchingGui {
42 36
@@ -80,35 +74,35 @@ public class ClassMatchingGui {
80 } 74 }
81 75
82 // controls 76 // controls
83 private JFrame m_frame; 77 private JFrame frame;
84 private ClassSelector m_sourceClasses; 78 private ClassSelector sourceClasses;
85 private ClassSelector m_destClasses; 79 private ClassSelector destClasses;
86 private CodeReader m_sourceReader; 80 private CodeReader sourceReader;
87 private CodeReader m_destReader; 81 private CodeReader destReader;
88 private JLabel m_sourceClassLabel; 82 private JLabel sourceClassLabel;
89 private JLabel m_destClassLabel; 83 private JLabel destClassLabel;
90 private JButton m_matchButton; 84 private JButton matchButton;
91 private Map<SourceType, JRadioButton> m_sourceTypeButtons; 85 private Map<SourceType, JRadioButton> sourceTypeButtons;
92 private JCheckBox m_advanceCheck; 86 private JCheckBox advanceCheck;
93 private JCheckBox m_top10Matches; 87 private JCheckBox top10Matches;
94 88
95 private ClassMatches m_classMatches; 89 private ClassMatches classMatches;
96 private Deobfuscator m_sourceDeobfuscator; 90 private Deobfuscator sourceDeobfuscator;
97 private Deobfuscator m_destDeobfuscator; 91 private Deobfuscator destDeobfuscator;
98 private ClassEntry m_sourceClass; 92 private ClassEntry sourceClass;
99 private ClassEntry m_destClass; 93 private ClassEntry destClass;
100 private SourceType m_sourceType; 94 private SourceType sourceType;
101 private SaveListener m_saveListener; 95 private SaveListener saveListener;
102 96
103 public ClassMatchingGui(ClassMatches matches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) { 97 public ClassMatchingGui(ClassMatches matches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) {
104 98
105 m_classMatches = matches; 99 classMatches = matches;
106 m_sourceDeobfuscator = sourceDeobfuscator; 100 this.sourceDeobfuscator = sourceDeobfuscator;
107 m_destDeobfuscator = destDeobfuscator; 101 this.destDeobfuscator = destDeobfuscator;
108 102
109 // init frame 103 // init frame
110 m_frame = new JFrame(Constants.NAME + " - Class Matcher"); 104 frame = new JFrame(Constants.NAME + " - Class Matcher");
111 final Container pane = m_frame.getContentPane(); 105 final Container pane = frame.getContentPane();
112 pane.setLayout(new BorderLayout()); 106 pane.setLayout(new BorderLayout());
113 107
114 // init source side 108 // init source side
@@ -124,16 +118,16 @@ public class ClassMatchingGui {
124 sourceTypePanel.setLayout(new BoxLayout(sourceTypePanel, BoxLayout.PAGE_AXIS)); 118 sourceTypePanel.setLayout(new BoxLayout(sourceTypePanel, BoxLayout.PAGE_AXIS));
125 ActionListener sourceTypeListener = event -> setSourceType(SourceType.valueOf(event.getActionCommand())); 119 ActionListener sourceTypeListener = event -> setSourceType(SourceType.valueOf(event.getActionCommand()));
126 ButtonGroup sourceTypeButtons = new ButtonGroup(); 120 ButtonGroup sourceTypeButtons = new ButtonGroup();
127 m_sourceTypeButtons = Maps.newHashMap(); 121 this.sourceTypeButtons = Maps.newHashMap();
128 for (SourceType sourceType : SourceType.values()) { 122 for (SourceType sourceType : SourceType.values()) {
129 JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons); 123 JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons);
130 m_sourceTypeButtons.put(sourceType, button); 124 this.sourceTypeButtons.put(sourceType, button);
131 sourceTypePanel.add(button); 125 sourceTypePanel.add(button);
132 } 126 }
133 127
134 m_sourceClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false); 128 sourceClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false);
135 m_sourceClasses.setSelectionListener(this::setSourceClass); 129 sourceClasses.setSelectionListener(this::setSourceClass);
136 JScrollPane sourceScroller = new JScrollPane(m_sourceClasses); 130 JScrollPane sourceScroller = new JScrollPane(sourceClasses);
137 sourcePanel.add(sourceScroller); 131 sourcePanel.add(sourceScroller);
138 132
139 // init dest side 133 // init dest side
@@ -143,13 +137,13 @@ public class ClassMatchingGui {
143 pane.add(destPanel, BorderLayout.WEST); 137 pane.add(destPanel, BorderLayout.WEST);
144 destPanel.add(new JLabel("Destination Classes")); 138 destPanel.add(new JLabel("Destination Classes"));
145 139
146 m_top10Matches = new JCheckBox("Show only top 10 matches"); 140 top10Matches = new JCheckBox("Show only top 10 matches");
147 destPanel.add(m_top10Matches); 141 destPanel.add(top10Matches);
148 m_top10Matches.addActionListener(event -> toggleTop10Matches()); 142 top10Matches.addActionListener(event -> toggleTop10Matches());
149 143
150 m_destClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false); 144 destClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false);
151 m_destClasses.setSelectionListener(this::setDestClass); 145 destClasses.setSelectionListener(this::setDestClass);
152 JScrollPane destScroller = new JScrollPane(m_destClasses); 146 JScrollPane destScroller = new JScrollPane(destClasses);
153 destPanel.add(destScroller); 147 destPanel.add(destScroller);
154 148
155 JButton autoMatchButton = new JButton("AutoMatch"); 149 JButton autoMatchButton = new JButton("AutoMatch");
@@ -158,13 +152,14 @@ public class ClassMatchingGui {
158 152
159 // init source panels 153 // init source panels
160 DefaultSyntaxKit.initKit(); 154 DefaultSyntaxKit.initKit();
161 m_sourceReader = new CodeReader(); 155 sourceReader = new CodeReader();
162 m_destReader = new CodeReader(); 156 destReader = new CodeReader();
163 157
164 // init all the splits 158 // init all the splits
165 JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, sourcePanel, new JScrollPane(m_sourceReader)); 159 JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, sourcePanel, new JScrollPane(
160 sourceReader));
166 splitLeft.setResizeWeight(0); // let the right side take all the slack 161 splitLeft.setResizeWeight(0); // let the right side take all the slack
167 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(m_destReader), destPanel); 162 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(destReader), destPanel);
168 splitRight.setResizeWeight(1); // let the left side take all the slack 163 splitRight.setResizeWeight(1); // let the left side take all the slack
169 JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, splitRight); 164 JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, splitRight);
170 splitCenter.setResizeWeight(0.5); // resize 50:50 165 splitCenter.setResizeWeight(0.5); // resize 50:50
@@ -175,55 +170,52 @@ public class ClassMatchingGui {
175 JPanel bottomPanel = new JPanel(); 170 JPanel bottomPanel = new JPanel();
176 bottomPanel.setLayout(new FlowLayout()); 171 bottomPanel.setLayout(new FlowLayout());
177 172
178 m_sourceClassLabel = new JLabel(); 173 sourceClassLabel = new JLabel();
179 m_sourceClassLabel.setHorizontalAlignment(SwingConstants.RIGHT); 174 sourceClassLabel.setHorizontalAlignment(SwingConstants.RIGHT);
180 m_destClassLabel = new JLabel(); 175 destClassLabel = new JLabel();
181 m_destClassLabel.setHorizontalAlignment(SwingConstants.LEFT); 176 destClassLabel.setHorizontalAlignment(SwingConstants.LEFT);
182 177
183 m_matchButton = new JButton(); 178 matchButton = new JButton();
184 179
185 m_advanceCheck = new JCheckBox("Advance to next likely match"); 180 advanceCheck = new JCheckBox("Advance to next likely match");
186 m_advanceCheck.addActionListener(event -> { 181 advanceCheck.addActionListener(event -> {
187 if (m_advanceCheck.isSelected()) { 182 if (advanceCheck.isSelected()) {
188 advance(); 183 advance();
189 } 184 }
190 }); 185 });
191 186
192 bottomPanel.add(m_sourceClassLabel); 187 bottomPanel.add(sourceClassLabel);
193 bottomPanel.add(m_matchButton); 188 bottomPanel.add(matchButton);
194 bottomPanel.add(m_destClassLabel); 189 bottomPanel.add(destClassLabel);
195 bottomPanel.add(m_advanceCheck); 190 bottomPanel.add(advanceCheck);
196 pane.add(bottomPanel, BorderLayout.SOUTH); 191 pane.add(bottomPanel, BorderLayout.SOUTH);
197 192
198 // show the frame 193 // show the frame
199 pane.doLayout(); 194 pane.doLayout();
200 m_frame.setSize(1024, 576); 195 frame.setSize(1024, 576);
201 m_frame.setMinimumSize(new Dimension(640, 480)); 196 frame.setMinimumSize(new Dimension(640, 480));
202 m_frame.setVisible(true); 197 frame.setVisible(true);
203 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 198 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
204 199
205 // init state 200 // init state
206 updateDestMappings(); 201 updateDestMappings();
207 setSourceType(SourceType.getDefault()); 202 setSourceType(SourceType.getDefault());
208 updateMatchButton(); 203 updateMatchButton();
209 m_saveListener = null; 204 saveListener = null;
210 } 205 }
211 206
212 public void setSaveListener(SaveListener val) { 207 public void setSaveListener(SaveListener val) {
213 m_saveListener = val; 208 saveListener = val;
214 } 209 }
215 210
216 private void updateDestMappings() { 211 private void updateDestMappings() {
217 try { 212 try {
218 Mappings newMappings = MappingsConverter.newMappings( 213 Mappings newMappings = MappingsConverter.newMappings(classMatches,
219 m_classMatches, 214 sourceDeobfuscator.getMappings(), sourceDeobfuscator, destDeobfuscator
220 m_sourceDeobfuscator.getMappings(),
221 m_sourceDeobfuscator,
222 m_destDeobfuscator
223 ); 215 );
224 216
225 // look for dropped mappings 217 // look for dropped mappings
226 MappingsChecker checker = new MappingsChecker(m_destDeobfuscator.getJarIndex()); 218 MappingsChecker checker = new MappingsChecker(destDeobfuscator.getJarIndex());
227 checker.dropBrokenMappings(newMappings); 219 checker.dropBrokenMappings(newMappings);
228 220
229 // count them 221 // count them
@@ -236,7 +228,7 @@ public class ClassMatchingGui {
236 numDroppedMethods 228 numDroppedMethods
237 )); 229 ));
238 230
239 m_destDeobfuscator.setMappings(newMappings); 231 destDeobfuscator.setMappings(newMappings);
240 } catch (MappingConflict ex) { 232 } catch (MappingConflict ex) {
241 System.out.println(ex.getMessage()); 233 System.out.println(ex.getMessage());
242 ex.printStackTrace(); 234 ex.printStackTrace();
@@ -247,14 +239,14 @@ public class ClassMatchingGui {
247 protected void setSourceType(SourceType val) { 239 protected void setSourceType(SourceType val) {
248 240
249 // show the source classes 241 // show the source classes
250 m_sourceType = val; 242 sourceType = val;
251 m_sourceClasses.setClasses(deobfuscateClasses(m_sourceType.getSourceClasses(m_classMatches), m_sourceDeobfuscator)); 243 sourceClasses.setClasses(deobfuscateClasses(sourceType.getSourceClasses(classMatches), sourceDeobfuscator));
252 244
253 // update counts 245 // update counts
254 for (SourceType sourceType : SourceType.values()) { 246 for (SourceType sourceType : SourceType.values()) {
255 m_sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)", 247 sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)",
256 sourceType.name(), 248 sourceType.name(),
257 sourceType.getSourceClasses(m_classMatches).size() 249 sourceType.getSourceClasses(classMatches).size()
258 )); 250 ));
259 } 251 }
260 } 252 }
@@ -278,7 +270,7 @@ public class ClassMatchingGui {
278 protected void setSourceClass(ClassEntry classEntry) { 270 protected void setSourceClass(ClassEntry classEntry) {
279 271
280 Runnable onGetDestClasses = null; 272 Runnable onGetDestClasses = null;
281 if (m_advanceCheck.isSelected()) { 273 if (advanceCheck.isSelected()) {
282 onGetDestClasses = this::pickBestDestClass; 274 onGetDestClasses = this::pickBestDestClass;
283 } 275 }
284 276
@@ -288,35 +280,33 @@ public class ClassMatchingGui {
288 protected void setSourceClass(ClassEntry classEntry, final Runnable onGetDestClasses) { 280 protected void setSourceClass(ClassEntry classEntry, final Runnable onGetDestClasses) {
289 281
290 // update the current source class 282 // update the current source class
291 m_sourceClass = classEntry; 283 sourceClass = classEntry;
292 m_sourceClassLabel.setText(m_sourceClass != null ? m_sourceClass.getName() : ""); 284 sourceClassLabel.setText(sourceClass != null ? sourceClass.getName() : "");
293 285
294 if (m_sourceClass != null) { 286 if (sourceClass != null) {
295 287
296 // show the dest class(es) 288 // show the dest class(es)
297 ClassMatch match = m_classMatches.getMatchBySource(m_sourceDeobfuscator.obfuscateEntry(m_sourceClass)); 289 ClassMatch match = classMatches.getMatchBySource(sourceDeobfuscator.obfuscateEntry(sourceClass));
298 assert (match != null); 290 assert (match != null);
299 if (match.destClasses.isEmpty()) { 291 if (match.destClasses.isEmpty()) {
300 292
301 m_destClasses.setClasses(null); 293 destClasses.setClasses(null);
302 294
303 // run in a separate thread to keep ui responsive 295 // run in a separate thread to keep ui responsive
304 new Thread() { 296 new Thread(() ->
305 @Override 297 {
306 public void run() { 298 destClasses.setClasses(deobfuscateClasses(getLikelyMatches(sourceClass), destDeobfuscator));
307 m_destClasses.setClasses(deobfuscateClasses(getLikelyMatches(m_sourceClass), m_destDeobfuscator)); 299 destClasses.expandAll();
308 m_destClasses.expandAll(); 300
309 301 if (onGetDestClasses != null) {
310 if (onGetDestClasses != null) { 302 onGetDestClasses.run();
311 onGetDestClasses.run();
312 }
313 } 303 }
314 }.start(); 304 }).start();
315 305
316 } else { 306 } else {
317 307
318 m_destClasses.setClasses(deobfuscateClasses(match.destClasses, m_destDeobfuscator)); 308 destClasses.setClasses(deobfuscateClasses(match.destClasses, destDeobfuscator));
319 m_destClasses.expandAll(); 309 destClasses.expandAll();
320 310
321 if (onGetDestClasses != null) { 311 if (onGetDestClasses != null) {
322 onGetDestClasses.run(); 312 onGetDestClasses.run();
@@ -325,23 +315,24 @@ public class ClassMatchingGui {
325 } 315 }
326 316
327 setDestClass(null); 317 setDestClass(null);
328 m_sourceReader.decompileClass(m_sourceClass, m_sourceDeobfuscator, () -> m_sourceReader.navigateToClassDeclaration(m_sourceClass)); 318 sourceReader.decompileClass(
319 sourceClass, sourceDeobfuscator, () -> sourceReader.navigateToClassDeclaration(sourceClass));
329 320
330 updateMatchButton(); 321 updateMatchButton();
331 } 322 }
332 323
333 private Collection<ClassEntry> getLikelyMatches(ClassEntry sourceClass) { 324 private Collection<ClassEntry> getLikelyMatches(ClassEntry sourceClass) {
334 325
335 ClassEntry obfSourceClass = m_sourceDeobfuscator.obfuscateEntry(sourceClass); 326 ClassEntry obfSourceClass = sourceDeobfuscator.obfuscateEntry(sourceClass);
336 327
337 // set up identifiers 328 // set up identifiers
338 ClassNamer namer = new ClassNamer(m_classMatches.getUniqueMatches()); 329 ClassNamer namer = new ClassNamer(classMatches.getUniqueMatches());
339 ClassIdentifier sourceIdentifier = new ClassIdentifier( 330 ClassIdentifier sourceIdentifier = new ClassIdentifier(
340 m_sourceDeobfuscator.getJar(), m_sourceDeobfuscator.getJarIndex(), 331 sourceDeobfuscator.getJar(), sourceDeobfuscator.getJarIndex(),
341 namer.getSourceNamer(), true 332 namer.getSourceNamer(), true
342 ); 333 );
343 ClassIdentifier destIdentifier = new ClassIdentifier( 334 ClassIdentifier destIdentifier = new ClassIdentifier(
344 m_destDeobfuscator.getJar(), m_destDeobfuscator.getJarIndex(), 335 destDeobfuscator.getJar(), destDeobfuscator.getJarIndex(),
345 namer.getDestNamer(), true 336 namer.getDestNamer(), true
346 ); 337 );
347 338
@@ -350,15 +341,16 @@ public class ClassMatchingGui {
350 // rank all the unmatched dest classes against the source class 341 // rank all the unmatched dest classes against the source class
351 ClassIdentity sourceIdentity = sourceIdentifier.identify(obfSourceClass); 342 ClassIdentity sourceIdentity = sourceIdentifier.identify(obfSourceClass);
352 List<ClassEntry> scoredDestClasses = Lists.newArrayList(); 343 List<ClassEntry> scoredDestClasses = Lists.newArrayList();
353 for (ClassEntry unmatchedDestClass : m_classMatches.getUnmatchedDestClasses()) { 344 for (ClassEntry unmatchedDestClass : classMatches.getUnmatchedDestClasses()) {
354 ClassIdentity destIdentity = destIdentifier.identify(unmatchedDestClass); 345 ClassIdentity destIdentity = destIdentifier.identify(unmatchedDestClass);
355 float score = 100.0f * (sourceIdentity.getMatchScore(destIdentity) + destIdentity.getMatchScore(sourceIdentity)) 346 float score = 100.0f * (sourceIdentity.getMatchScore(destIdentity) + destIdentity.getMatchScore(sourceIdentity))
356 / (sourceIdentity.getMaxMatchScore() + destIdentity.getMaxMatchScore()); 347 / (sourceIdentity.getMaxMatchScore() + destIdentity.getMaxMatchScore());
357 scoredDestClasses.add(new ScoredClassEntry(unmatchedDestClass, score)); 348 scoredDestClasses.add(new ScoredClassEntry(unmatchedDestClass, score));
358 } 349 }
359 350
360 if (m_top10Matches.isSelected() && scoredDestClasses.size() > 10) { 351 if (top10Matches.isSelected() && scoredDestClasses.size() > 10) {
361 Collections.sort(scoredDestClasses, (a, b) -> { 352 scoredDestClasses.sort((a, b) ->
353 {
362 ScoredClassEntry sa = (ScoredClassEntry) a; 354 ScoredClassEntry sa = (ScoredClassEntry) a;
363 ScoredClassEntry sb = (ScoredClassEntry) b; 355 ScoredClassEntry sb = (ScoredClassEntry) b;
364 return -Float.compare(sa.getScore(), sb.getScore()); 356 return -Float.compare(sa.getScore(), sb.getScore());
@@ -376,30 +368,30 @@ public class ClassMatchingGui {
376 protected void setDestClass(ClassEntry classEntry) { 368 protected void setDestClass(ClassEntry classEntry) {
377 369
378 // update the current source class 370 // update the current source class
379 m_destClass = classEntry; 371 destClass = classEntry;
380 m_destClassLabel.setText(m_destClass != null ? m_destClass.getName() : ""); 372 destClassLabel.setText(destClass != null ? destClass.getName() : "");
381 373
382 m_destReader.decompileClass(m_destClass, m_destDeobfuscator, () -> m_destReader.navigateToClassDeclaration(m_destClass)); 374 destReader.decompileClass(destClass, destDeobfuscator, () -> destReader.navigateToClassDeclaration(destClass));
383 375
384 updateMatchButton(); 376 updateMatchButton();
385 } 377 }
386 378
387 private void updateMatchButton() { 379 private void updateMatchButton() {
388 380
389 ClassEntry obfSource = m_sourceDeobfuscator.obfuscateEntry(m_sourceClass); 381 ClassEntry obfSource = sourceDeobfuscator.obfuscateEntry(sourceClass);
390 ClassEntry obfDest = m_destDeobfuscator.obfuscateEntry(m_destClass); 382 ClassEntry obfDest = destDeobfuscator.obfuscateEntry(destClass);
391 383
392 BiMap<ClassEntry, ClassEntry> uniqueMatches = m_classMatches.getUniqueMatches(); 384 BiMap<ClassEntry, ClassEntry> uniqueMatches = classMatches.getUniqueMatches();
393 boolean twoSelected = m_sourceClass != null && m_destClass != null; 385 boolean twoSelected = sourceClass != null && destClass != null;
394 boolean isMatched = uniqueMatches.containsKey(obfSource) && uniqueMatches.containsValue(obfDest); 386 boolean isMatched = uniqueMatches.containsKey(obfSource) && uniqueMatches.containsValue(obfDest);
395 boolean canMatch = !uniqueMatches.containsKey(obfSource) && !uniqueMatches.containsValue(obfDest); 387 boolean canMatch = !uniqueMatches.containsKey(obfSource) && !uniqueMatches.containsValue(obfDest);
396 388
397 GuiTricks.deactivateButton(m_matchButton); 389 GuiTricks.deactivateButton(matchButton);
398 if (twoSelected) { 390 if (twoSelected) {
399 if (isMatched) { 391 if (isMatched) {
400 GuiTricks.activateButton(m_matchButton, "Unmatch", event -> onUnmatchClick()); 392 GuiTricks.activateButton(matchButton, "Unmatch", event -> onUnmatchClick());
401 } else if (canMatch) { 393 } else if (canMatch) {
402 GuiTricks.activateButton(m_matchButton, "Match", event -> onMatchClick()); 394 GuiTricks.activateButton(matchButton, "Match", event -> onMatchClick());
403 } 395 }
404 } 396 }
405 } 397 }
@@ -407,19 +399,19 @@ public class ClassMatchingGui {
407 private void onMatchClick() { 399 private void onMatchClick() {
408 // precondition: source and dest classes are set correctly 400 // precondition: source and dest classes are set correctly
409 401
410 ClassEntry obfSource = m_sourceDeobfuscator.obfuscateEntry(m_sourceClass); 402 ClassEntry obfSource = sourceDeobfuscator.obfuscateEntry(sourceClass);
411 ClassEntry obfDest = m_destDeobfuscator.obfuscateEntry(m_destClass); 403 ClassEntry obfDest = destDeobfuscator.obfuscateEntry(destClass);
412 404
413 // remove the classes from their match 405 // remove the classes from their match
414 m_classMatches.removeSource(obfSource); 406 classMatches.removeSource(obfSource);
415 m_classMatches.removeDest(obfDest); 407 classMatches.removeDest(obfDest);
416 408
417 // add them as matched classes 409 // add them as matched classes
418 m_classMatches.add(new ClassMatch(obfSource, obfDest)); 410 classMatches.add(new ClassMatch(obfSource, obfDest));
419 411
420 ClassEntry nextClass = null; 412 ClassEntry nextClass = null;
421 if (m_advanceCheck.isSelected()) { 413 if (advanceCheck.isSelected()) {
422 nextClass = m_sourceClasses.getNextClass(m_sourceClass); 414 nextClass = sourceClasses.getNextClass(sourceClass);
423 } 415 }
424 416
425 save(); 417 save();
@@ -433,11 +425,11 @@ public class ClassMatchingGui {
433 private void onUnmatchClick() { 425 private void onUnmatchClick() {
434 // precondition: source and dest classes are set to a unique match 426 // precondition: source and dest classes are set to a unique match
435 427
436 ClassEntry obfSource = m_sourceDeobfuscator.obfuscateEntry(m_sourceClass); 428 ClassEntry obfSource = sourceDeobfuscator.obfuscateEntry(sourceClass);
437 429
438 // remove the source to break the match, then add the source back as unmatched 430 // remove the source to break the match, then add the source back as unmatched
439 m_classMatches.removeSource(obfSource); 431 classMatches.removeSource(obfSource);
440 m_classMatches.add(new ClassMatch(obfSource, null)); 432 classMatches.add(new ClassMatch(obfSource, null));
441 433
442 save(); 434 save();
443 updateMatches(); 435 updateMatches();
@@ -446,20 +438,20 @@ public class ClassMatchingGui {
446 private void updateMatches() { 438 private void updateMatches() {
447 updateDestMappings(); 439 updateDestMappings();
448 setDestClass(null); 440 setDestClass(null);
449 m_destClasses.setClasses(null); 441 destClasses.setClasses(null);
450 updateMatchButton(); 442 updateMatchButton();
451 443
452 // remember where we were in the source tree 444 // remember where we were in the source tree
453 String packageName = m_sourceClasses.getSelectedPackage(); 445 String packageName = sourceClasses.getSelectedPackage();
454 446
455 setSourceType(m_sourceType); 447 setSourceType(sourceType);
456 448
457 m_sourceClasses.expandPackage(packageName); 449 sourceClasses.expandPackage(packageName);
458 } 450 }
459 451
460 private void save() { 452 private void save() {
461 if (m_saveListener != null) { 453 if (saveListener != null) {
462 m_saveListener.save(m_classMatches); 454 saveListener.save(classMatches);
463 } 455 }
464 } 456 }
465 457
@@ -469,17 +461,17 @@ public class ClassMatchingGui {
469 461
470 // compute a new matching 462 // compute a new matching
471 ClassMatching matching = MappingsConverter.computeMatching( 463 ClassMatching matching = MappingsConverter.computeMatching(
472 m_sourceDeobfuscator.getJar(), m_sourceDeobfuscator.getJarIndex(), 464 sourceDeobfuscator.getJar(), sourceDeobfuscator.getJarIndex(),
473 m_destDeobfuscator.getJar(), m_destDeobfuscator.getJarIndex(), 465 destDeobfuscator.getJar(), destDeobfuscator.getJarIndex(),
474 m_classMatches.getUniqueMatches() 466 classMatches.getUniqueMatches()
475 ); 467 );
476 ClassMatches newMatches = new ClassMatches(matching.matches()); 468 ClassMatches newMatches = new ClassMatches(matching.matches());
477 System.out.println(String.format("Automatch found %d new matches", 469 System.out.println(String.format("Automatch found %d new matches",
478 newMatches.getUniqueMatches().size() - m_classMatches.getUniqueMatches().size() 470 newMatches.getUniqueMatches().size() - classMatches.getUniqueMatches().size()
479 )); 471 ));
480 472
481 // update the current matches 473 // update the current matches
482 m_classMatches = newMatches; 474 classMatches = newMatches;
483 save(); 475 save();
484 updateMatches(); 476 updateMatches();
485 } 477 }
@@ -492,17 +484,17 @@ public class ClassMatchingGui {
492 484
493 // make sure we have a source class 485 // make sure we have a source class
494 if (sourceClass == null) { 486 if (sourceClass == null) {
495 sourceClass = m_sourceClasses.getSelectedClass(); 487 sourceClass = sourceClasses.getSelectedClass();
496 if (sourceClass != null) { 488 if (sourceClass != null) {
497 sourceClass = m_sourceClasses.getNextClass(sourceClass); 489 sourceClass = sourceClasses.getNextClass(sourceClass);
498 } else { 490 } else {
499 sourceClass = m_sourceClasses.getFirstClass(); 491 sourceClass = sourceClasses.getFirstClass();
500 } 492 }
501 } 493 }
502 494
503 // set the source class 495 // set the source class
504 setSourceClass(sourceClass, this::pickBestDestClass); 496 setSourceClass(sourceClass, this::pickBestDestClass);
505 m_sourceClasses.setSelectionClass(sourceClass); 497 sourceClasses.setSelectionClass(sourceClass);
506 } 498 }
507 499
508 private void pickBestDestClass() { 500 private void pickBestDestClass() {
@@ -510,8 +502,8 @@ public class ClassMatchingGui {
510 // then, pick the best dest class 502 // then, pick the best dest class
511 ClassEntry firstClass = null; 503 ClassEntry firstClass = null;
512 ScoredClassEntry bestDestClass = null; 504 ScoredClassEntry bestDestClass = null;
513 for (ClassSelectorPackageNode packageNode : m_destClasses.packageNodes()) { 505 for (ClassSelectorPackageNode packageNode : destClasses.packageNodes()) {
514 for (ClassSelectorClassNode classNode : m_destClasses.classNodes(packageNode)) { 506 for (ClassSelectorClassNode classNode : destClasses.classNodes(packageNode)) {
515 if (firstClass == null) { 507 if (firstClass == null) {
516 firstClass = classNode.getClassEntry(); 508 firstClass = classNode.getClassEntry();
517 } 509 }
@@ -533,14 +525,14 @@ public class ClassMatchingGui {
533 } 525 }
534 526
535 setDestClass(destClass); 527 setDestClass(destClass);
536 m_destClasses.setSelectionClass(destClass); 528 destClasses.setSelectionClass(destClass);
537 } 529 }
538 530
539 private void toggleTop10Matches() { 531 private void toggleTop10Matches() {
540 if (m_sourceClass != null) { 532 if (sourceClass != null) {
541 m_destClasses.clearSelection(); 533 destClasses.clearSelection();
542 m_destClasses.setClasses(deobfuscateClasses(getLikelyMatches(m_sourceClass), m_destDeobfuscator)); 534 destClasses.setClasses(deobfuscateClasses(getLikelyMatches(sourceClass), destDeobfuscator));
543 m_destClasses.expandAll(); 535 destClasses.expandAll();
544 } 536 }
545 } 537 }
546} 538}
diff --git a/src/main/java/cuchaz/enigma/gui/ClassSelector.java b/src/main/java/cuchaz/enigma/gui/ClassSelector.java
index 435509e..8ece0a0 100644
--- a/src/main/java/cuchaz/enigma/gui/ClassSelector.java
+++ b/src/main/java/cuchaz/enigma/gui/ClassSelector.java
@@ -29,7 +29,7 @@ import java.util.*;
29 29
30public class ClassSelector extends JTree { 30public class ClassSelector extends JTree {
31 31
32 public static final Comparator<ClassEntry> DEOBF_CLASS_COMPARATOR = (a, b) -> a.getName().compareTo(b.getName()); 32 public static final Comparator<ClassEntry> DEOBF_CLASS_COMPARATOR = Comparator.comparing(ClassEntry::getName);
33 private DefaultMutableTreeNode rootNodes; 33 private DefaultMutableTreeNode rootNodes;
34 34
35 public interface ClassSelectionListener { 35 public interface ClassSelectionListener {
@@ -177,25 +177,32 @@ public class ClassSelector extends JTree {
177 177
178 // sort the packages 178 // sort the packages
179 List<String> sortedPackageNames = Lists.newArrayList(packages.keySet()); 179 List<String> sortedPackageNames = Lists.newArrayList(packages.keySet());
180 Collections.sort(sortedPackageNames, (a, b) -> { 180 sortedPackageNames.sort((a, b) ->
181 {
181 // I can never keep this rule straight when writing these damn things... 182 // I can never keep this rule straight when writing these damn things...
182 // a < b => -1, a == b => 0, a > b => +1 183 // a < b => -1, a == b => 0, a > b => +1
183 184
184 if(b == null || a == null){ 185 if (b == null || a == null)
186 {
185 return 0; 187 return 0;
186 } 188 }
187 189
188 String[] aparts = a.split("/"); 190 String[] aparts = a.split("/");
189 String[] bparts = b.split("/"); 191 String[] bparts = b.split("/");
190 for (int i = 0; true; i++) { 192 for (int i = 0; true; i++)
191 if (i >= aparts.length) { 193 {
194 if (i >= aparts.length)
195 {
192 return -1; 196 return -1;
193 } else if (i >= bparts.length) { 197 }
198 else if (i >= bparts.length)
199 {
194 return 1; 200 return 1;
195 } 201 }
196 202
197 int result = aparts[i].compareTo(bparts[i]); 203 int result = aparts[i].compareTo(bparts[i]);
198 if (result != 0) { 204 if (result != 0)
205 {
199 return result; 206 return result;
200 } 207 }
201 } 208 }
@@ -219,7 +226,7 @@ public class ClassSelector extends JTree {
219 for (String packageName : packagedClassEntries.keySet()) { 226 for (String packageName : packagedClassEntries.keySet()) {
220 // sort the class entries 227 // sort the class entries
221 List<ClassEntry> classEntriesInPackage = Lists.newArrayList(packagedClassEntries.get(packageName)); 228 List<ClassEntry> classEntriesInPackage = Lists.newArrayList(packagedClassEntries.get(packageName));
222 Collections.sort(classEntriesInPackage, this.comparator); 229 classEntriesInPackage.sort(this.comparator);
223 230
224 // create the nodes in order 231 // create the nodes in order
225 for (ClassEntry classEntry : classEntriesInPackage) { 232 for (ClassEntry classEntry : classEntriesInPackage) {
@@ -274,7 +281,7 @@ public class ClassSelector extends JTree {
274 281
275 public String getExpansionState(JTree tree, int row) { 282 public String getExpansionState(JTree tree, int row) {
276 TreePath rowPath = tree.getPathForRow(row); 283 TreePath rowPath = tree.getPathForRow(row);
277 StringBuffer buf = new StringBuffer(); 284 StringBuilder buf = new StringBuilder();
278 int rowCount = tree.getRowCount(); 285 int rowCount = tree.getRowCount();
279 for (int i = row; i < rowCount; i++) { 286 for (int i = row; i < rowCount; i++) {
280 TreePath path = tree.getPathForRow(i); 287 TreePath path = tree.getPathForRow(i);
@@ -500,7 +507,7 @@ public class ClassSelector extends JTree {
500 { 507 {
501 List<ClassSelectorClassNode> classNodes = classNodes(newPackageNode); 508 List<ClassSelectorClassNode> classNodes = classNodes(newPackageNode);
502 classNodes.add(classNode); 509 classNodes.add(classNode);
503 Collections.sort(classNodes, (a, b) -> a.toString().compareTo(b.toString())); 510 classNodes.sort(Comparator.comparing(ClassSelectorClassNode::toString));
504 for (int i = 0; i < classNodes.size(); i++) 511 for (int i = 0; i < classNodes.size(); i++)
505 if (classNodes.get(i) == classNode) 512 if (classNodes.get(i) == classNode)
506 return i; 513 return i;
@@ -514,7 +521,7 @@ public class ClassSelector extends JTree {
514 if (!packageNodes.contains(newPackageNode)) 521 if (!packageNodes.contains(newPackageNode))
515 { 522 {
516 packageNodes.add(newPackageNode); 523 packageNodes.add(newPackageNode);
517 Collections.sort(packageNodes, (a, b) -> a.toString().compareTo(b.toString())); 524 packageNodes.sort(Comparator.comparing(ClassSelectorPackageNode::toString));
518 } 525 }
519 526
520 for (int i = 0; i < packageNodes.size(); i++) 527 for (int i = 0; i < packageNodes.size(); i++)
diff --git a/src/main/java/cuchaz/enigma/gui/CodeReader.java b/src/main/java/cuchaz/enigma/gui/CodeReader.java
index 601e5b9..8225d8f 100644
--- a/src/main/java/cuchaz/enigma/gui/CodeReader.java
+++ b/src/main/java/cuchaz/enigma/gui/CodeReader.java
@@ -19,8 +19,6 @@ import java.awt.event.ActionListener;
19import javax.swing.JEditorPane; 19import javax.swing.JEditorPane;
20import javax.swing.SwingUtilities; 20import javax.swing.SwingUtilities;
21import javax.swing.Timer; 21import javax.swing.Timer;
22import javax.swing.event.CaretEvent;
23import javax.swing.event.CaretListener;
24import javax.swing.text.BadLocationException; 22import javax.swing.text.BadLocationException;
25import javax.swing.text.Highlighter.HighlightPainter; 23import javax.swing.text.Highlighter.HighlightPainter;
26 24
@@ -38,15 +36,15 @@ public class CodeReader extends JEditorPane {
38 36
39 private static final long serialVersionUID = 3673180950485748810L; 37 private static final long serialVersionUID = 3673180950485748810L;
40 38
41 private static final Object m_lock = new Object(); 39 private static final Object lock = new Object();
42 40
43 public interface SelectionListener { 41 public interface SelectionListener {
44 void onSelect(EntryReference<Entry, Entry> reference); 42 void onSelect(EntryReference<Entry, Entry> reference);
45 } 43 }
46 44
47 private SelectionHighlightPainter m_selectionHighlightPainter; 45 private SelectionHighlightPainter selectionHighlightPainter;
48 private SourceIndex m_sourceIndex; 46 private SourceIndex sourceIndex;
49 private SelectionListener m_selectionListener; 47 private SelectionListener selectionListener;
50 48
51 public CodeReader() { 49 public CodeReader() {
52 50
@@ -58,38 +56,34 @@ public class CodeReader extends JEditorPane {
58 kit.toggleComponent(this, "de.sciss.syntaxpane.components.TokenMarker"); 56 kit.toggleComponent(this, "de.sciss.syntaxpane.components.TokenMarker");
59 57
60 // hook events 58 // hook events
61 addCaretListener(new CaretListener() { 59 addCaretListener(event ->
62 @Override 60 {
63 public void caretUpdate(CaretEvent event) { 61 if (selectionListener != null && sourceIndex != null) {
64 if (m_selectionListener != null && m_sourceIndex != null) { 62 Token token = sourceIndex.getReferenceToken(event.getDot());
65 Token token = m_sourceIndex.getReferenceToken(event.getDot()); 63 if (token != null) {
66 if (token != null) { 64 selectionListener.onSelect(sourceIndex.getDeobfReference(token));
67 m_selectionListener.onSelect(m_sourceIndex.getDeobfReference(token)); 65 } else {
68 } else { 66 selectionListener.onSelect(null);
69 m_selectionListener.onSelect(null);
70 }
71 } 67 }
72 } 68 }
73 }); 69 });
74 70
75 m_selectionHighlightPainter = new SelectionHighlightPainter(); 71 selectionHighlightPainter = new SelectionHighlightPainter();
76 m_sourceIndex = null;
77 m_selectionListener = null;
78 } 72 }
79 73
80 public void setSelectionListener(SelectionListener val) { 74 public void setSelectionListener(SelectionListener val) {
81 m_selectionListener = val; 75 selectionListener = val;
82 } 76 }
83 77
84 public void setCode(String code) { 78 public void setCode(String code) {
85 // sadly, the java lexer is not thread safe, so we have to serialize all these calls 79 // sadly, the java lexer is not thread safe, so we have to serialize all these calls
86 synchronized (m_lock) { 80 synchronized (lock) {
87 setText(code); 81 setText(code);
88 } 82 }
89 } 83 }
90 84
91 public SourceIndex getSourceIndex() { 85 public SourceIndex getSourceIndex() {
92 return m_sourceIndex; 86 return sourceIndex;
93 } 87 }
94 88
95 public void decompileClass(ClassEntry classEntry, Deobfuscator deobfuscator) { 89 public void decompileClass(ClassEntry classEntry, Deobfuscator deobfuscator) {
@@ -110,33 +104,31 @@ public class CodeReader extends JEditorPane {
110 setCode("(decompiling...)"); 104 setCode("(decompiling...)");
111 105
112 // run decompilation in a separate thread to keep ui responsive 106 // run decompilation in a separate thread to keep ui responsive
113 new Thread() { 107 new Thread(() ->
114 @Override 108 {
115 public void run() {
116 109
117 // decompile it 110 // decompile it
118 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getOutermostClassName()); 111 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getOutermostClassName());
119 String source = deobfuscator.getSource(sourceTree); 112 String source = deobfuscator.getSource(sourceTree);
120 setCode(source); 113 setCode(source);
121 m_sourceIndex = deobfuscator.getSourceIndex(sourceTree, source, ignoreBadTokens); 114 sourceIndex = deobfuscator.getSourceIndex(sourceTree, source, ignoreBadTokens);
122 115
123 if (callback != null) { 116 if (callback != null) {
124 callback.run(); 117 callback.run();
125 }
126 } 118 }
127 }.start(); 119 }).start();
128 } 120 }
129 121
130 public void navigateToClassDeclaration(ClassEntry classEntry) { 122 public void navigateToClassDeclaration(ClassEntry classEntry) {
131 123
132 // navigate to the class declaration 124 // navigate to the class declaration
133 Token token = m_sourceIndex.getDeclarationToken(classEntry); 125 Token token = sourceIndex.getDeclarationToken(classEntry);
134 if (token == null) { 126 if (token == null) {
135 // couldn't find the class declaration token, might be an anonymous class 127 // couldn't find the class declaration token, might be an anonymous class
136 // look for any declaration in that class instead 128 // look for any declaration in that class instead
137 for (Entry entry : m_sourceIndex.declarations()) { 129 for (Entry entry : sourceIndex.declarations()) {
138 if (entry.getClassEntry().equals(classEntry)) { 130 if (entry.getClassEntry().equals(classEntry)) {
139 token = m_sourceIndex.getDeclarationToken(entry); 131 token = sourceIndex.getDeclarationToken(entry);
140 break; 132 break;
141 } 133 }
142 } 134 }
@@ -151,7 +143,7 @@ public class CodeReader extends JEditorPane {
151 } 143 }
152 144
153 public void navigateToToken(final Token token) { 145 public void navigateToToken(final Token token) {
154 navigateToToken(this, token, m_selectionHighlightPainter); 146 navigateToToken(this, token, selectionHighlightPainter);
155 } 147 }
156 148
157 // HACKHACK: someday we can update the main GUI to use this code reader 149 // HACKHACK: someday we can update the main GUI to use this code reader
@@ -167,34 +159,29 @@ public class CodeReader extends JEditorPane {
167 Rectangle end = editor.modelToView(token.end); 159 Rectangle end = editor.modelToView(token.end);
168 final Rectangle show = start.union(end); 160 final Rectangle show = start.union(end);
169 show.grow(start.width * 10, start.height * 6); 161 show.grow(start.width * 10, start.height * 6);
170 SwingUtilities.invokeLater(new Runnable() { 162 SwingUtilities.invokeLater(() -> editor.scrollRectToVisible(show));
171 @Override
172 public void run() {
173 editor.scrollRectToVisible(show);
174 }
175 });
176 } catch (BadLocationException ex) { 163 } catch (BadLocationException ex) {
177 throw new Error(ex); 164 throw new Error(ex);
178 } 165 }
179 166
180 // highlight the token momentarily 167 // highlight the token momentarily
181 final Timer timer = new Timer(200, new ActionListener() { 168 final Timer timer = new Timer(200, new ActionListener() {
182 private int m_counter = 0; 169 private int counter = 0;
183 private Object m_highlight = null; 170 private Object highlight = null;
184 171
185 @Override 172 @Override
186 public void actionPerformed(ActionEvent event) { 173 public void actionPerformed(ActionEvent event) {
187 if (m_counter % 2 == 0) { 174 if (counter % 2 == 0) {
188 try { 175 try {
189 m_highlight = editor.getHighlighter().addHighlight(token.start, token.end, highlightPainter); 176 highlight = editor.getHighlighter().addHighlight(token.start, token.end, highlightPainter);
190 } catch (BadLocationException ex) { 177 } catch (BadLocationException ex) {
191 // don't care 178 // don't care
192 } 179 }
193 } else if (m_highlight != null) { 180 } else if (highlight != null) {
194 editor.getHighlighter().removeHighlight(m_highlight); 181 editor.getHighlighter().removeHighlight(highlight);
195 } 182 }
196 183
197 if (m_counter++ > 6) { 184 if (counter++ > 6) {
198 Timer timer = (Timer) event.getSource(); 185 Timer timer = (Timer) event.getSource();
199 timer.stop(); 186 timer.stop();
200 } 187 }
diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java
index ed18777..7cb494f 100644
--- a/src/main/java/cuchaz/enigma/gui/Gui.java
+++ b/src/main/java/cuchaz/enigma/gui/Gui.java
@@ -62,23 +62,23 @@ public class Gui {
62 private final MenuBar menuBar; 62 private final MenuBar menuBar;
63 public final PopupMenuBar popupMenu; 63 public final PopupMenuBar popupMenu;
64 64
65 private JFrame frame; 65 private JFrame frame;
66 private PanelEditor editor; 66 private PanelEditor editor;
67 private JPanel classesPanel; 67 private JPanel classesPanel;
68 private JSplitPane m_splitClasses; 68 private JSplitPane splitClasses;
69 private PanelIdentifier m_infoPanel; 69 private PanelIdentifier infoPanel;
70 private ObfuscatedHighlightPainter m_obfuscatedHighlightPainter; 70 private ObfuscatedHighlightPainter obfuscatedHighlightPainter;
71 private DeobfuscatedHighlightPainter m_deobfuscatedHighlightPainter; 71 private DeobfuscatedHighlightPainter deobfuscatedHighlightPainter;
72 private OtherHighlightPainter m_otherHighlightPainter; 72 private OtherHighlightPainter otherHighlightPainter;
73 private SelectionHighlightPainter m_selectionHighlightPainter; 73 private SelectionHighlightPainter selectionHighlightPainter;
74 private JTree m_inheritanceTree; 74 private JTree inheritanceTree;
75 private JTree m_implementationsTree; 75 private JTree implementationsTree;
76 private JTree m_callsTree; 76 private JTree callsTree;
77 private JList<Token> m_tokens; 77 private JList<Token> tokens;
78 private JTabbedPane m_tabs; 78 private JTabbedPane tabs;
79 79
80 // state 80 // state
81 public EntryReference<Entry, Entry> m_reference; 81 public EntryReference<Entry, Entry> reference;
82 82
83 public JFileChooser jarFileChooser; 83 public JFileChooser jarFileChooser;
84 public JFileChooser enigmaMappingsFileChooser; 84 public JFileChooser enigmaMappingsFileChooser;
@@ -118,22 +118,22 @@ public class Gui {
118 this.deobfPanel = new PanelDeobf(this); 118 this.deobfPanel = new PanelDeobf(this);
119 119
120 // set up classes panel (don't add the splitter yet) 120 // set up classes panel (don't add the splitter yet)
121 m_splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, this.obfPanel, this.deobfPanel); 121 splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, this.obfPanel, this.deobfPanel);
122 m_splitClasses.setResizeWeight(0.3); 122 splitClasses.setResizeWeight(0.3);
123 this.classesPanel = new JPanel(); 123 this.classesPanel = new JPanel();
124 this.classesPanel.setLayout(new BorderLayout()); 124 this.classesPanel.setLayout(new BorderLayout());
125 this.classesPanel.setPreferredSize(new Dimension(250, 0)); 125 this.classesPanel.setPreferredSize(new Dimension(250, 0));
126 126
127 // init info panel 127 // init info panel
128 m_infoPanel = new PanelIdentifier(this); 128 infoPanel = new PanelIdentifier(this);
129 m_infoPanel.clearReference(); 129 infoPanel.clearReference();
130 130
131 // init editor 131 // init editor
132 DefaultSyntaxKit.initKit(); 132 DefaultSyntaxKit.initKit();
133 m_obfuscatedHighlightPainter = new ObfuscatedHighlightPainter(); 133 obfuscatedHighlightPainter = new ObfuscatedHighlightPainter();
134 m_deobfuscatedHighlightPainter = new DeobfuscatedHighlightPainter(); 134 deobfuscatedHighlightPainter = new DeobfuscatedHighlightPainter();
135 m_otherHighlightPainter = new OtherHighlightPainter(); 135 otherHighlightPainter = new OtherHighlightPainter();
136 m_selectionHighlightPainter = new SelectionHighlightPainter(); 136 selectionHighlightPainter = new SelectionHighlightPainter();
137 this.editor = new PanelEditor(this); 137 this.editor = new PanelEditor(this);
138 JScrollPane sourceScroller = new JScrollPane(this.editor); 138 JScrollPane sourceScroller = new JScrollPane(this.editor);
139 this.editor.setContentType("text/java"); 139 this.editor.setContentType("text/java");
@@ -145,14 +145,14 @@ public class Gui {
145 this.editor.setComponentPopupMenu(this.popupMenu); 145 this.editor.setComponentPopupMenu(this.popupMenu);
146 146
147 // init inheritance panel 147 // init inheritance panel
148 m_inheritanceTree = new JTree(); 148 inheritanceTree = new JTree();
149 m_inheritanceTree.setModel(null); 149 inheritanceTree.setModel(null);
150 m_inheritanceTree.addMouseListener(new MouseAdapter() { 150 inheritanceTree.addMouseListener(new MouseAdapter() {
151 @Override 151 @Override
152 public void mouseClicked(MouseEvent event) { 152 public void mouseClicked(MouseEvent event) {
153 if (event.getClickCount() == 2) { 153 if (event.getClickCount() == 2) {
154 // get the selected node 154 // get the selected node
155 TreePath path = m_inheritanceTree.getSelectionPath(); 155 TreePath path = inheritanceTree.getSelectionPath();
156 if (path == null) { 156 if (path == null) {
157 return; 157 return;
158 } 158 }
@@ -172,17 +172,17 @@ public class Gui {
172 }); 172 });
173 JPanel inheritancePanel = new JPanel(); 173 JPanel inheritancePanel = new JPanel();
174 inheritancePanel.setLayout(new BorderLayout()); 174 inheritancePanel.setLayout(new BorderLayout());
175 inheritancePanel.add(new JScrollPane(m_inheritanceTree)); 175 inheritancePanel.add(new JScrollPane(inheritanceTree));
176 176
177 // init implementations panel 177 // init implementations panel
178 m_implementationsTree = new JTree(); 178 implementationsTree = new JTree();
179 m_implementationsTree.setModel(null); 179 implementationsTree.setModel(null);
180 m_implementationsTree.addMouseListener(new MouseAdapter() { 180 implementationsTree.addMouseListener(new MouseAdapter() {
181 @Override 181 @Override
182 public void mouseClicked(MouseEvent event) { 182 public void mouseClicked(MouseEvent event) {
183 if (event.getClickCount() == 2) { 183 if (event.getClickCount() == 2) {
184 // get the selected node 184 // get the selected node
185 TreePath path = m_implementationsTree.getSelectionPath(); 185 TreePath path = implementationsTree.getSelectionPath();
186 if (path == null) { 186 if (path == null) {
187 return; 187 return;
188 } 188 }
@@ -200,18 +200,18 @@ public class Gui {
200 }); 200 });
201 JPanel implementationsPanel = new JPanel(); 201 JPanel implementationsPanel = new JPanel();
202 implementationsPanel.setLayout(new BorderLayout()); 202 implementationsPanel.setLayout(new BorderLayout());
203 implementationsPanel.add(new JScrollPane(m_implementationsTree)); 203 implementationsPanel.add(new JScrollPane(implementationsTree));
204 204
205 // init call panel 205 // init call panel
206 m_callsTree = new JTree(); 206 callsTree = new JTree();
207 m_callsTree.setModel(null); 207 callsTree.setModel(null);
208 m_callsTree.addMouseListener(new MouseAdapter() { 208 callsTree.addMouseListener(new MouseAdapter() {
209 @SuppressWarnings("unchecked") 209 @SuppressWarnings("unchecked")
210 @Override 210 @Override
211 public void mouseClicked(MouseEvent event) { 211 public void mouseClicked(MouseEvent event) {
212 if (event.getClickCount() == 2) { 212 if (event.getClickCount() == 2) {
213 // get the selected node 213 // get the selected node
214 TreePath path = m_callsTree.getSelectionPath(); 214 TreePath path = callsTree.getSelectionPath();
215 if (path == null) { 215 if (path == null) {
216 return; 216 return;
217 } 217 }
@@ -228,28 +228,28 @@ public class Gui {
228 } 228 }
229 } 229 }
230 }); 230 });
231 m_tokens = new JList<>(); 231 tokens = new JList<>();
232 m_tokens.setCellRenderer(new TokenListCellRenderer(this.controller)); 232 tokens.setCellRenderer(new TokenListCellRenderer(this.controller));
233 m_tokens.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 233 tokens.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
234 m_tokens.setLayoutOrientation(JList.VERTICAL); 234 tokens.setLayoutOrientation(JList.VERTICAL);
235 m_tokens.addMouseListener(new MouseAdapter() { 235 tokens.addMouseListener(new MouseAdapter() {
236 @Override 236 @Override
237 public void mouseClicked(MouseEvent event) { 237 public void mouseClicked(MouseEvent event) {
238 if (event.getClickCount() == 2) { 238 if (event.getClickCount() == 2) {
239 Token selected = m_tokens.getSelectedValue(); 239 Token selected = tokens.getSelectedValue();
240 if (selected != null) { 240 if (selected != null) {
241 showToken(selected); 241 showToken(selected);
242 } 242 }
243 } 243 }
244 } 244 }
245 }); 245 });
246 m_tokens.setPreferredSize(new Dimension(0, 200)); 246 tokens.setPreferredSize(new Dimension(0, 200));
247 m_tokens.setMinimumSize(new Dimension(0, 200)); 247 tokens.setMinimumSize(new Dimension(0, 200));
248 JSplitPane callPanel = new JSplitPane( 248 JSplitPane callPanel = new JSplitPane(
249 JSplitPane.VERTICAL_SPLIT, 249 JSplitPane.VERTICAL_SPLIT,
250 true, 250 true,
251 new JScrollPane(m_callsTree), 251 new JScrollPane(callsTree),
252 new JScrollPane(m_tokens) 252 new JScrollPane(tokens)
253 ); 253 );
254 callPanel.setResizeWeight(1); // let the top side take all the slack 254 callPanel.setResizeWeight(1); // let the top side take all the slack
255 callPanel.resetToPreferredSizes(); 255 callPanel.resetToPreferredSizes();
@@ -257,14 +257,14 @@ public class Gui {
257 // layout controls 257 // layout controls
258 JPanel centerPanel = new JPanel(); 258 JPanel centerPanel = new JPanel();
259 centerPanel.setLayout(new BorderLayout()); 259 centerPanel.setLayout(new BorderLayout());
260 centerPanel.add(m_infoPanel, BorderLayout.NORTH); 260 centerPanel.add(infoPanel, BorderLayout.NORTH);
261 centerPanel.add(sourceScroller, BorderLayout.CENTER); 261 centerPanel.add(sourceScroller, BorderLayout.CENTER);
262 m_tabs = new JTabbedPane(); 262 tabs = new JTabbedPane();
263 m_tabs.setPreferredSize(new Dimension(250, 0)); 263 tabs.setPreferredSize(new Dimension(250, 0));
264 m_tabs.addTab("Inheritance", inheritancePanel); 264 tabs.addTab("Inheritance", inheritancePanel);
265 m_tabs.addTab("Implementations", implementationsPanel); 265 tabs.addTab("Implementations", implementationsPanel);
266 m_tabs.addTab("Call Graph", callPanel); 266 tabs.addTab("Call Graph", callPanel);
267 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs); 267 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, tabs);
268 splitRight.setResizeWeight(1); // let the left side take all the slack 268 splitRight.setResizeWeight(1); // let the left side take all the slack
269 splitRight.resetToPreferredSizes(); 269 splitRight.resetToPreferredSizes();
270 JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.classesPanel, splitRight); 270 JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.classesPanel, splitRight);
@@ -314,7 +314,7 @@ public class Gui {
314 // update gui 314 // update gui
315 this.frame.setTitle(Constants.NAME + " - " + jarName); 315 this.frame.setTitle(Constants.NAME + " - " + jarName);
316 this.classesPanel.removeAll(); 316 this.classesPanel.removeAll();
317 this.classesPanel.add(m_splitClasses); 317 this.classesPanel.add(splitClasses);
318 setSource(null); 318 setSource(null);
319 319
320 // update menu 320 // update menu
@@ -375,7 +375,7 @@ public class Gui {
375 if (token == null) { 375 if (token == null) {
376 throw new IllegalArgumentException("Token cannot be null!"); 376 throw new IllegalArgumentException("Token cannot be null!");
377 } 377 }
378 CodeReader.navigateToToken(this.editor, token, m_selectionHighlightPainter); 378 CodeReader.navigateToToken(this.editor, token, selectionHighlightPainter);
379 redraw(); 379 redraw();
380 } 380 }
381 381
@@ -384,10 +384,10 @@ public class Gui {
384 Collections.sort(sortedTokens); 384 Collections.sort(sortedTokens);
385 if (sortedTokens.size() > 1) { 385 if (sortedTokens.size() > 1) {
386 // sort the tokens and update the tokens panel 386 // sort the tokens and update the tokens panel
387 m_tokens.setListData(sortedTokens); 387 this.tokens.setListData(sortedTokens);
388 m_tokens.setSelectedIndex(0); 388 this.tokens.setSelectedIndex(0);
389 } else { 389 } else {
390 m_tokens.setListData(new Vector<>()); 390 this.tokens.setListData(new Vector<>());
391 } 391 }
392 392
393 // show the first token 393 // show the first token
@@ -401,13 +401,13 @@ public class Gui {
401 401
402 // color things based on the index 402 // color things based on the index
403 if (obfuscatedTokens != null) { 403 if (obfuscatedTokens != null) {
404 setHighlightedTokens(obfuscatedTokens, m_obfuscatedHighlightPainter); 404 setHighlightedTokens(obfuscatedTokens, obfuscatedHighlightPainter);
405 } 405 }
406 if (deobfuscatedTokens != null) { 406 if (deobfuscatedTokens != null) {
407 setHighlightedTokens(deobfuscatedTokens, m_deobfuscatedHighlightPainter); 407 setHighlightedTokens(deobfuscatedTokens, deobfuscatedHighlightPainter);
408 } 408 }
409 if (otherTokens != null) { 409 if (otherTokens != null) {
410 setHighlightedTokens(otherTokens, m_otherHighlightPainter); 410 setHighlightedTokens(otherTokens, otherHighlightPainter);
411 } 411 }
412 412
413 redraw(); 413 redraw();
@@ -425,73 +425,73 @@ public class Gui {
425 425
426 private void showReference(EntryReference<Entry, Entry> reference) { 426 private void showReference(EntryReference<Entry, Entry> reference) {
427 if (reference == null) { 427 if (reference == null) {
428 m_infoPanel.clearReference(); 428 infoPanel.clearReference();
429 return; 429 return;
430 } 430 }
431 431
432 m_reference = reference; 432 this.reference = reference;
433 433
434 m_infoPanel.removeAll(); 434 infoPanel.removeAll();
435 if (reference.entry instanceof ClassEntry) { 435 if (reference.entry instanceof ClassEntry) {
436 showClassEntry((ClassEntry) m_reference.entry); 436 showClassEntry((ClassEntry) this.reference.entry);
437 } else if (m_reference.entry instanceof FieldEntry) { 437 } else if (this.reference.entry instanceof FieldEntry) {
438 showFieldEntry((FieldEntry) m_reference.entry); 438 showFieldEntry((FieldEntry) this.reference.entry);
439 } else if (m_reference.entry instanceof MethodEntry) { 439 } else if (this.reference.entry instanceof MethodEntry) {
440 showMethodEntry((MethodEntry) m_reference.entry); 440 showMethodEntry((MethodEntry) this.reference.entry);
441 } else if (m_reference.entry instanceof ConstructorEntry) { 441 } else if (this.reference.entry instanceof ConstructorEntry) {
442 showConstructorEntry((ConstructorEntry) m_reference.entry); 442 showConstructorEntry((ConstructorEntry) this.reference.entry);
443 } else if (m_reference.entry instanceof ArgumentEntry) { 443 } else if (this.reference.entry instanceof ArgumentEntry) {
444 showArgumentEntry((ArgumentEntry) m_reference.entry); 444 showArgumentEntry((ArgumentEntry) this.reference.entry);
445 } else if (m_reference.entry instanceof LocalVariableEntry) { 445 } else if (this.reference.entry instanceof LocalVariableEntry) {
446 showLocalVariableEntry((LocalVariableEntry) m_reference.entry); 446 showLocalVariableEntry((LocalVariableEntry) this.reference.entry);
447 } else { 447 } else {
448 throw new Error("Unknown entry type: " + m_reference.entry.getClass().getName()); 448 throw new Error("Unknown entry type: " + this.reference.entry.getClass().getName());
449 } 449 }
450 450
451 redraw(); 451 redraw();
452 } 452 }
453 453
454 private void showLocalVariableEntry(LocalVariableEntry entry) { 454 private void showLocalVariableEntry(LocalVariableEntry entry) {
455 addNameValue(m_infoPanel, "Variable", entry.getName()); 455 addNameValue(infoPanel, "Variable", entry.getName());
456 addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); 456 addNameValue(infoPanel, "Class", entry.getClassEntry().getName());
457 addNameValue(m_infoPanel, "Method", entry.getBehaviorEntry().getName()); 457 addNameValue(infoPanel, "Method", entry.getBehaviorEntry().getName());
458 addNameValue(m_infoPanel, "Index", Integer.toString(entry.getIndex())); 458 addNameValue(infoPanel, "Index", Integer.toString(entry.getIndex()));
459 addNameValue(m_infoPanel, "Type", entry.getType().toString()); 459 addNameValue(infoPanel, "Type", entry.getType().toString());
460 } 460 }
461 461
462 private void showClassEntry(ClassEntry entry) { 462 private void showClassEntry(ClassEntry entry) {
463 addNameValue(m_infoPanel, "Class", entry.getName()); 463 addNameValue(infoPanel, "Class", entry.getName());
464 addModifierComboBox(m_infoPanel, "Modifier", entry); 464 addModifierComboBox(infoPanel, "Modifier", entry);
465 } 465 }
466 466
467 private void showFieldEntry(FieldEntry entry) { 467 private void showFieldEntry(FieldEntry entry) {
468 addNameValue(m_infoPanel, "Field", entry.getName()); 468 addNameValue(infoPanel, "Field", entry.getName());
469 addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); 469 addNameValue(infoPanel, "Class", entry.getClassEntry().getName());
470 addNameValue(m_infoPanel, "Type", entry.getType().toString()); 470 addNameValue(infoPanel, "Type", entry.getType().toString());
471 addModifierComboBox(m_infoPanel, "Modifier", entry); 471 addModifierComboBox(infoPanel, "Modifier", entry);
472 } 472 }
473 473
474 private void showMethodEntry(MethodEntry entry) { 474 private void showMethodEntry(MethodEntry entry) {
475 addNameValue(m_infoPanel, "Method", entry.getName()); 475 addNameValue(infoPanel, "Method", entry.getName());
476 addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); 476 addNameValue(infoPanel, "Class", entry.getClassEntry().getName());
477 addNameValue(m_infoPanel, "Signature", entry.getSignature().toString()); 477 addNameValue(infoPanel, "Signature", entry.getSignature().toString());
478 addModifierComboBox(m_infoPanel, "Modifier", entry); 478 addModifierComboBox(infoPanel, "Modifier", entry);
479 479
480 } 480 }
481 481
482 private void showConstructorEntry(ConstructorEntry entry) { 482 private void showConstructorEntry(ConstructorEntry entry) {
483 addNameValue(m_infoPanel, "Constructor", entry.getClassEntry().getName()); 483 addNameValue(infoPanel, "Constructor", entry.getClassEntry().getName());
484 if (!entry.isStatic()) { 484 if (!entry.isStatic()) {
485 addNameValue(m_infoPanel, "Signature", entry.getSignature().toString()); 485 addNameValue(infoPanel, "Signature", entry.getSignature().toString());
486 addModifierComboBox(m_infoPanel, "Modifier", entry); 486 addModifierComboBox(infoPanel, "Modifier", entry);
487 } 487 }
488 } 488 }
489 489
490 private void showArgumentEntry(ArgumentEntry entry) { 490 private void showArgumentEntry(ArgumentEntry entry) {
491 addNameValue(m_infoPanel, "Argument", entry.getName()); 491 addNameValue(infoPanel, "Argument", entry.getName());
492 addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); 492 addNameValue(infoPanel, "Class", entry.getClassEntry().getName());
493 addNameValue(m_infoPanel, "Method", entry.getBehaviorEntry().getName()); 493 addNameValue(infoPanel, "Method", entry.getBehaviorEntry().getName());
494 addNameValue(m_infoPanel, "Index", Integer.toString(entry.getIndex())); 494 addNameValue(infoPanel, "Index", Integer.toString(entry.getIndex()));
495 } 495 }
496 496
497 private void addNameValue(JPanel container, String name, String value) { 497 private void addNameValue(JPanel container, String name, String value) {
@@ -530,18 +530,18 @@ public class Gui {
530 Token token = this.controller.getToken(pos); 530 Token token = this.controller.getToken(pos);
531 boolean isToken = token != null; 531 boolean isToken = token != null;
532 532
533 m_reference = this.controller.getDeobfReference(token); 533 reference = this.controller.getDeobfReference(token);
534 boolean isClassEntry = isToken && m_reference.entry instanceof ClassEntry; 534 boolean isClassEntry = isToken && reference.entry instanceof ClassEntry;
535 boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; 535 boolean isFieldEntry = isToken && reference.entry instanceof FieldEntry;
536 boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; 536 boolean isMethodEntry = isToken && reference.entry instanceof MethodEntry;
537 boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; 537 boolean isConstructorEntry = isToken && reference.entry instanceof ConstructorEntry;
538 boolean isInJar = isToken && this.controller.entryIsInJar(m_reference.entry); 538 boolean isInJar = isToken && this.controller.entryIsInJar(reference.entry);
539 boolean isRenameable = isToken && this.controller.referenceIsRenameable(m_reference); 539 boolean isRenameable = isToken && this.controller.referenceIsRenameable(reference);
540 540
541 if (isToken) { 541 if (isToken) {
542 showReference(m_reference); 542 showReference(reference);
543 } else { 543 } else {
544 m_infoPanel.clearReference(); 544 infoPanel.clearReference();
545 } 545 }
546 546
547 this.popupMenu.renameMenu.setEnabled(isRenameable); 547 this.popupMenu.renameMenu.setEnabled(isRenameable);
@@ -552,7 +552,7 @@ public class Gui {
552 this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousLocation()); 552 this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousLocation());
553 this.popupMenu.toggleMappingMenu.setEnabled(isRenameable); 553 this.popupMenu.toggleMappingMenu.setEnabled(isRenameable);
554 554
555 if (isToken && this.controller.entryHasDeobfuscatedName(m_reference.entry)) { 555 if (isToken && this.controller.entryHasDeobfuscatedName(reference.entry)) {
556 this.popupMenu.toggleMappingMenu.setText("Reset to obfuscated"); 556 this.popupMenu.toggleMappingMenu.setText("Reset to obfuscated");
557 } else { 557 } else {
558 this.popupMenu.toggleMappingMenu.setText("Mark as deobfuscated"); 558 this.popupMenu.toggleMappingMenu.setText("Mark as deobfuscated");
@@ -564,8 +564,8 @@ public class Gui {
564 // entry is not in the jar. Ignore it 564 // entry is not in the jar. Ignore it
565 return; 565 return;
566 } 566 }
567 if (m_reference != null) { 567 if (reference != null) {
568 this.controller.savePreviousReference(m_reference); 568 this.controller.savePreviousReference(reference);
569 } 569 }
570 this.controller.openDeclaration(entry); 570 this.controller.openDeclaration(entry);
571 } 571 }
@@ -574,8 +574,8 @@ public class Gui {
574 if (!this.controller.entryIsInJar(reference.getLocationClassEntry())) { 574 if (!this.controller.entryIsInJar(reference.getLocationClassEntry())) {
575 return; 575 return;
576 } 576 }
577 if (m_reference != null) { 577 if (this.reference != null) {
578 this.controller.savePreviousReference(m_reference); 578 this.controller.savePreviousReference(this.reference);
579 } 579 }
580 this.controller.openReference(reference); 580 this.controller.openReference(reference);
581 } 581 }
@@ -584,7 +584,7 @@ public class Gui {
584 584
585 // init the text box 585 // init the text box
586 final JTextField text = new JTextField(); 586 final JTextField text = new JTextField();
587 text.setText(m_reference.getNamableName()); 587 text.setText(reference.getNamableName());
588 text.setPreferredSize(new Dimension(360, text.getPreferredSize().height)); 588 text.setPreferredSize(new Dimension(360, text.getPreferredSize().height));
589 text.addKeyListener(new KeyAdapter() { 589 text.addKeyListener(new KeyAdapter() {
590 @Override 590 @Override
@@ -604,14 +604,14 @@ public class Gui {
604 }); 604 });
605 605
606 // find the label with the name and replace it with the text box 606 // find the label with the name and replace it with the text box
607 JPanel panel = (JPanel) m_infoPanel.getComponent(0); 607 JPanel panel = (JPanel) infoPanel.getComponent(0);
608 panel.remove(panel.getComponentCount() - 1); 608 panel.remove(panel.getComponentCount() - 1);
609 panel.add(text); 609 panel.add(text);
610 text.grabFocus(); 610 text.grabFocus();
611 611
612 int offset = text.getText().lastIndexOf('/') + 1; 612 int offset = text.getText().lastIndexOf('/') + 1;
613 // If it's a class and isn't in the default package, assume that it's deobfuscated. 613 // If it's a class and isn't in the default package, assume that it's deobfuscated.
614 if (m_reference.getNameableEntry() instanceof ClassEntry && text.getText().contains("/") && offset != 0) 614 if (reference.getNameableEntry() instanceof ClassEntry && text.getText().contains("/") && offset != 0)
615 text.select(offset, text.getText().length()); 615 text.select(offset, text.getText().length());
616 else 616 else
617 text.selectAll(); 617 text.selectAll();
@@ -623,7 +623,7 @@ public class Gui {
623 String newName = text.getText(); 623 String newName = text.getText();
624 if (saveName && newName != null && newName.length() > 0) { 624 if (saveName && newName != null && newName.length() > 0) {
625 try { 625 try {
626 this.controller.rename(m_reference, newName); 626 this.controller.rename(reference, newName);
627 } catch (IllegalNameException ex) { 627 } catch (IllegalNameException ex) {
628 text.setBorder(BorderFactory.createLineBorder(Color.red, 1)); 628 text.setBorder(BorderFactory.createLineBorder(Color.red, 1));
629 text.setToolTipText(ex.getReason()); 629 text.setToolTipText(ex.getReason());
@@ -633,9 +633,9 @@ public class Gui {
633 } 633 }
634 634
635 // abort the rename 635 // abort the rename
636 JPanel panel = (JPanel) m_infoPanel.getComponent(0); 636 JPanel panel = (JPanel) infoPanel.getComponent(0);
637 panel.remove(panel.getComponentCount() - 1); 637 panel.remove(panel.getComponentCount() - 1);
638 panel.add(Utils.unboldLabel(new JLabel(m_reference.getNamableName(), JLabel.LEFT))); 638 panel.add(Utils.unboldLabel(new JLabel(reference.getNamableName(), JLabel.LEFT)));
639 639
640 this.editor.grabFocus(); 640 this.editor.grabFocus();
641 641
@@ -644,95 +644,95 @@ public class Gui {
644 644
645 public void showInheritance() { 645 public void showInheritance() {
646 646
647 if (m_reference == null) { 647 if (reference == null) {
648 return; 648 return;
649 } 649 }
650 650
651 m_inheritanceTree.setModel(null); 651 inheritanceTree.setModel(null);
652 652
653 if (m_reference.entry instanceof ClassEntry) { 653 if (reference.entry instanceof ClassEntry) {
654 // get the class inheritance 654 // get the class inheritance
655 ClassInheritanceTreeNode classNode = this.controller.getClassInheritance((ClassEntry) m_reference.entry); 655 ClassInheritanceTreeNode classNode = this.controller.getClassInheritance((ClassEntry) reference.entry);
656 656
657 // show the tree at the root 657 // show the tree at the root
658 TreePath path = getPathToRoot(classNode); 658 TreePath path = getPathToRoot(classNode);
659 m_inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); 659 inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0)));
660 m_inheritanceTree.expandPath(path); 660 inheritanceTree.expandPath(path);
661 m_inheritanceTree.setSelectionRow(m_inheritanceTree.getRowForPath(path)); 661 inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path));
662 } else if (m_reference.entry instanceof MethodEntry) { 662 } else if (reference.entry instanceof MethodEntry) {
663 // get the method inheritance 663 // get the method inheritance
664 MethodInheritanceTreeNode classNode = this.controller.getMethodInheritance((MethodEntry) m_reference.entry); 664 MethodInheritanceTreeNode classNode = this.controller.getMethodInheritance((MethodEntry) reference.entry);
665 665
666 // show the tree at the root 666 // show the tree at the root
667 TreePath path = getPathToRoot(classNode); 667 TreePath path = getPathToRoot(classNode);
668 m_inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); 668 inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0)));
669 m_inheritanceTree.expandPath(path); 669 inheritanceTree.expandPath(path);
670 m_inheritanceTree.setSelectionRow(m_inheritanceTree.getRowForPath(path)); 670 inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path));
671 } 671 }
672 672
673 m_tabs.setSelectedIndex(0); 673 tabs.setSelectedIndex(0);
674 redraw(); 674 redraw();
675 } 675 }
676 676
677 public void showImplementations() { 677 public void showImplementations() {
678 678
679 if (m_reference == null) { 679 if (reference == null) {
680 return; 680 return;
681 } 681 }
682 682
683 m_implementationsTree.setModel(null); 683 implementationsTree.setModel(null);
684 684
685 DefaultMutableTreeNode node = null; 685 DefaultMutableTreeNode node = null;
686 686
687 // get the class implementations 687 // get the class implementations
688 if (m_reference.entry instanceof ClassEntry) 688 if (reference.entry instanceof ClassEntry)
689 node = this.controller.getClassImplementations((ClassEntry) m_reference.entry); 689 node = this.controller.getClassImplementations((ClassEntry) reference.entry);
690 else // get the method implementations 690 else // get the method implementations
691 if (m_reference.entry instanceof MethodEntry) 691 if (reference.entry instanceof MethodEntry)
692 node = this.controller.getMethodImplementations((MethodEntry) m_reference.entry); 692 node = this.controller.getMethodImplementations((MethodEntry) reference.entry);
693 693
694 if (node != null) { 694 if (node != null) {
695 // show the tree at the root 695 // show the tree at the root
696 TreePath path = getPathToRoot(node); 696 TreePath path = getPathToRoot(node);
697 m_implementationsTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); 697 implementationsTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0)));
698 m_implementationsTree.expandPath(path); 698 implementationsTree.expandPath(path);
699 m_implementationsTree.setSelectionRow(m_implementationsTree.getRowForPath(path)); 699 implementationsTree.setSelectionRow(implementationsTree.getRowForPath(path));
700 } 700 }
701 701
702 m_tabs.setSelectedIndex(1); 702 tabs.setSelectedIndex(1);
703 redraw(); 703 redraw();
704 } 704 }
705 705
706 public void showCalls() { 706 public void showCalls() {
707 if (m_reference == null) { 707 if (reference == null) {
708 return; 708 return;
709 } 709 }
710 710
711 if (m_reference.entry instanceof ClassEntry) { 711 if (reference.entry instanceof ClassEntry) {
712 // look for calls to the default constructor 712 // look for calls to the default constructor
713 // TODO: get a list of all the constructors and find calls to all of them 713 // TODO: get a list of all the constructors and find calls to all of them
714 BehaviorReferenceTreeNode node = this.controller.getMethodReferences(new ConstructorEntry((ClassEntry) m_reference.entry, new Signature("()V"))); 714 BehaviorReferenceTreeNode node = this.controller.getMethodReferences(new ConstructorEntry((ClassEntry) reference.entry, new Signature("()V")));
715 m_callsTree.setModel(new DefaultTreeModel(node)); 715 callsTree.setModel(new DefaultTreeModel(node));
716 } else if (m_reference.entry instanceof FieldEntry) { 716 } else if (reference.entry instanceof FieldEntry) {
717 FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) m_reference.entry); 717 FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) reference.entry);
718 m_callsTree.setModel(new DefaultTreeModel(node)); 718 callsTree.setModel(new DefaultTreeModel(node));
719 } else if (m_reference.entry instanceof MethodEntry) { 719 } else if (reference.entry instanceof MethodEntry) {
720 BehaviorReferenceTreeNode node = this.controller.getMethodReferences((MethodEntry) m_reference.entry); 720 BehaviorReferenceTreeNode node = this.controller.getMethodReferences((MethodEntry) reference.entry);
721 m_callsTree.setModel(new DefaultTreeModel(node)); 721 callsTree.setModel(new DefaultTreeModel(node));
722 } else if (m_reference.entry instanceof ConstructorEntry) { 722 } else if (reference.entry instanceof ConstructorEntry) {
723 BehaviorReferenceTreeNode node = this.controller.getMethodReferences((ConstructorEntry) m_reference.entry); 723 BehaviorReferenceTreeNode node = this.controller.getMethodReferences((ConstructorEntry) reference.entry);
724 m_callsTree.setModel(new DefaultTreeModel(node)); 724 callsTree.setModel(new DefaultTreeModel(node));
725 } 725 }
726 726
727 m_tabs.setSelectedIndex(2); 727 tabs.setSelectedIndex(2);
728 redraw(); 728 redraw();
729 } 729 }
730 730
731 public void toggleMapping() { 731 public void toggleMapping() {
732 if (this.controller.entryHasDeobfuscatedName(m_reference.entry)) { 732 if (this.controller.entryHasDeobfuscatedName(reference.entry)) {
733 this.controller.removeMapping(m_reference); 733 this.controller.removeMapping(reference);
734 } else { 734 } else {
735 this.controller.markAsDeobfuscated(m_reference); 735 this.controller.markAsDeobfuscated(reference);
736 } 736 }
737 } 737 }
738 738
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java
index c2e202e..68fd484 100644
--- a/src/main/java/cuchaz/enigma/gui/GuiController.java
+++ b/src/main/java/cuchaz/enigma/gui/GuiController.java
@@ -50,7 +50,7 @@ public class GuiController {
50 return this.isDirty; 50 return this.isDirty;
51 } 51 }
52 52
53 public void openJar(final JarFile jar) throws IOException { 53 public void openJar(final JarFile jar) {
54 this.gui.onStartOpenJar(); 54 this.gui.onStartOpenJar();
55 this.deobfuscator = new Deobfuscator(jar); 55 this.deobfuscator = new Deobfuscator(jar);
56 this.gui.onFinishOpenJar(this.deobfuscator.getJarName()); 56 this.gui.onFinishOpenJar(this.deobfuscator.getJarName());
@@ -302,42 +302,40 @@ public class GuiController {
302 this.gui.setSource("(deobfuscating...)"); 302 this.gui.setSource("(deobfuscating...)");
303 303
304 // run the deobfuscator in a separate thread so we don't block the GUI event queue 304 // run the deobfuscator in a separate thread so we don't block the GUI event queue
305 new Thread() { 305 new Thread(() ->
306 @Override 306 {
307 public void run() { 307 // decompile,deobfuscate the bytecode
308 // decompile,deobfuscate the bytecode 308 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getClassName());
309 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getClassName()); 309 if (sourceTree == null) {
310 if (sourceTree == null) { 310 // decompilation of this class is not supported
311 // decompilation of this class is not supported 311 gui.setSource("Unable to find class: " + classEntry);
312 gui.setSource("Unable to find class: " + classEntry); 312 return;
313 return; 313 }
314 } 314 String source = deobfuscator.getSource(sourceTree);
315 String source = deobfuscator.getSource(sourceTree); 315 index = deobfuscator.getSourceIndex(sourceTree, source);
316 index = deobfuscator.getSourceIndex(sourceTree, source); 316 gui.setSource(index.getSource());
317 gui.setSource(index.getSource()); 317 if (obfReference != null) {
318 if (obfReference != null) { 318 showReference(obfReference);
319 showReference(obfReference); 319 }
320 }
321 320
322 // set the highlighted tokens 321 // set the highlighted tokens
323 List<Token> obfuscatedTokens = Lists.newArrayList(); 322 List<Token> obfuscatedTokens = Lists.newArrayList();
324 List<Token> deobfuscatedTokens = Lists.newArrayList(); 323 List<Token> deobfuscatedTokens = Lists.newArrayList();
325 List<Token> otherTokens = Lists.newArrayList(); 324 List<Token> otherTokens = Lists.newArrayList();
326 for (Token token : index.referenceTokens()) { 325 for (Token token : index.referenceTokens()) {
327 EntryReference<Entry, Entry> reference = index.getDeobfReference(token); 326 EntryReference<Entry, Entry> reference = index.getDeobfReference(token);
328 if (referenceIsRenameable(reference)) { 327 if (referenceIsRenameable(reference)) {
329 if (entryHasDeobfuscatedName(reference.getNameableEntry())) { 328 if (entryHasDeobfuscatedName(reference.getNameableEntry())) {
330 deobfuscatedTokens.add(token); 329 deobfuscatedTokens.add(token);
331 } else {
332 obfuscatedTokens.add(token);
333 }
334 } else { 330 } else {
335 otherTokens.add(token); 331 obfuscatedTokens.add(token);
336 } 332 }
333 } else {
334 otherTokens.add(token);
337 } 335 }
338 gui.setHighlightedTokens(obfuscatedTokens, deobfuscatedTokens, otherTokens);
339 } 336 }
340 }.start(); 337 gui.setHighlightedTokens(obfuscatedTokens, deobfuscatedTokens, otherTokens);
338 }).start();
341 } 339 }
342 340
343 public Deobfuscator getDeobfuscator() 341 public Deobfuscator getDeobfuscator()
@@ -349,7 +347,7 @@ public class GuiController {
349 { 347 {
350 if (event.getStateChange() == ItemEvent.SELECTED) 348 if (event.getStateChange() == ItemEvent.SELECTED)
351 { 349 {
352 deobfuscator.changeModifier(gui.m_reference.entry, (Mappings.EntryModifier) event.getItem()); 350 deobfuscator.changeModifier(gui.reference.entry, (Mappings.EntryModifier) event.getItem());
353 this.isDirty = true; 351 this.isDirty = true;
354 refreshCurrentClass(); 352 refreshCurrentClass();
355 } 353 }
diff --git a/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java b/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java
index ecc280d..671f85f 100644
--- a/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java
+++ b/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java
@@ -17,7 +17,6 @@ import java.awt.BorderLayout;
17import java.awt.Container; 17import java.awt.Container;
18import java.awt.Dimension; 18import java.awt.Dimension;
19import java.awt.FlowLayout; 19import java.awt.FlowLayout;
20import java.awt.event.ActionEvent;
21import java.awt.event.ActionListener; 20import java.awt.event.ActionListener;
22import java.awt.event.KeyAdapter; 21import java.awt.event.KeyAdapter;
23import java.awt.event.KeyEvent; 22import java.awt.event.KeyEvent;
@@ -30,7 +29,6 @@ import javax.swing.text.Highlighter.HighlightPainter;
30 29
31import cuchaz.enigma.Constants; 30import cuchaz.enigma.Constants;
32import cuchaz.enigma.Deobfuscator; 31import cuchaz.enigma.Deobfuscator;
33import cuchaz.enigma.analysis.EntryReference;
34import cuchaz.enigma.analysis.SourceIndex; 32import cuchaz.enigma.analysis.SourceIndex;
35import cuchaz.enigma.analysis.Token; 33import cuchaz.enigma.analysis.Token;
36import cuchaz.enigma.convert.ClassMatches; 34import cuchaz.enigma.convert.ClassMatches;
@@ -78,39 +76,38 @@ public class MemberMatchingGui<T extends Entry> {
78 } 76 }
79 77
80 // controls 78 // controls
81 private JFrame m_frame; 79 private JFrame frame;
82 private Map<SourceType, JRadioButton> m_sourceTypeButtons; 80 private Map<SourceType, JRadioButton> sourceTypeButtons;
83 private ClassSelector m_sourceClasses; 81 private ClassSelector sourceClasses;
84 private CodeReader m_sourceReader; 82 private CodeReader sourceReader;
85 private CodeReader m_destReader; 83 private CodeReader destReader;
86 private JButton m_matchButton; 84 private JButton matchButton;
87 private JButton m_unmatchableButton; 85 private JButton unmatchableButton;
88 private JLabel m_sourceLabel; 86 private JLabel sourceLabel;
89 private JLabel m_destLabel; 87 private JLabel destLabel;
90 private HighlightPainter m_unmatchedHighlightPainter; 88 private HighlightPainter unmatchedHighlightPainter;
91 private HighlightPainter m_matchedHighlightPainter; 89 private HighlightPainter matchedHighlightPainter;
92 90 private ClassMatches classMatches;
93 private ClassMatches m_classMatches; 91 private MemberMatches<T> memberMatches;
94 private MemberMatches<T> m_memberMatches; 92 private Deobfuscator sourceDeobfuscator;
95 private Deobfuscator m_sourceDeobfuscator; 93 private Deobfuscator destDeobfuscator;
96 private Deobfuscator m_destDeobfuscator; 94 private SaveListener<T> saveListener;
97 private SaveListener<T> m_saveListener; 95 private SourceType sourceType;
98 private SourceType m_sourceType; 96 private ClassEntry obfSourceClass;
99 private ClassEntry m_obfSourceClass; 97 private ClassEntry obfDestClass;
100 private ClassEntry m_obfDestClass; 98 private T obfSourceEntry;
101 private T m_obfSourceEntry; 99 private T obfDestEntry;
102 private T m_obfDestEntry;
103 100
104 public MemberMatchingGui(ClassMatches classMatches, MemberMatches<T> fieldMatches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) { 101 public MemberMatchingGui(ClassMatches classMatches, MemberMatches<T> fieldMatches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) {
105 102
106 m_classMatches = classMatches; 103 this.classMatches = classMatches;
107 m_memberMatches = fieldMatches; 104 memberMatches = fieldMatches;
108 m_sourceDeobfuscator = sourceDeobfuscator; 105 this.sourceDeobfuscator = sourceDeobfuscator;
109 m_destDeobfuscator = destDeobfuscator; 106 this.destDeobfuscator = destDeobfuscator;
110 107
111 // init frame 108 // init frame
112 m_frame = new JFrame(Constants.NAME + " - Member Matcher"); 109 frame = new JFrame(Constants.NAME + " - Member Matcher");
113 final Container pane = m_frame.getContentPane(); 110 final Container pane = frame.getContentPane();
114 pane.setLayout(new BorderLayout()); 111 pane.setLayout(new BorderLayout());
115 112
116 // init classes side 113 // init classes side
@@ -124,47 +121,38 @@ public class MemberMatchingGui<T extends Entry> {
124 JPanel sourceTypePanel = new JPanel(); 121 JPanel sourceTypePanel = new JPanel();
125 classesPanel.add(sourceTypePanel); 122 classesPanel.add(sourceTypePanel);
126 sourceTypePanel.setLayout(new BoxLayout(sourceTypePanel, BoxLayout.PAGE_AXIS)); 123 sourceTypePanel.setLayout(new BoxLayout(sourceTypePanel, BoxLayout.PAGE_AXIS));
127 ActionListener sourceTypeListener = new ActionListener() { 124 ActionListener sourceTypeListener = event -> setSourceType(SourceType.valueOf(event.getActionCommand()));
128 @Override
129 public void actionPerformed(ActionEvent event) {
130 setSourceType(SourceType.valueOf(event.getActionCommand()));
131 }
132 };
133 ButtonGroup sourceTypeButtons = new ButtonGroup(); 125 ButtonGroup sourceTypeButtons = new ButtonGroup();
134 m_sourceTypeButtons = Maps.newHashMap(); 126 this.sourceTypeButtons = Maps.newHashMap();
135 for (SourceType sourceType : SourceType.values()) { 127 for (SourceType sourceType : SourceType.values()) {
136 JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons); 128 JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons);
137 m_sourceTypeButtons.put(sourceType, button); 129 this.sourceTypeButtons.put(sourceType, button);
138 sourceTypePanel.add(button); 130 sourceTypePanel.add(button);
139 } 131 }
140 132
141 m_sourceClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false); 133 sourceClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false);
142 m_sourceClasses.setSelectionListener(this::setSourceClass); 134 sourceClasses.setSelectionListener(this::setSourceClass);
143 JScrollPane sourceScroller = new JScrollPane(m_sourceClasses); 135 JScrollPane sourceScroller = new JScrollPane(sourceClasses);
144 classesPanel.add(sourceScroller); 136 classesPanel.add(sourceScroller);
145 137
146 // init readers 138 // init readers
147 DefaultSyntaxKit.initKit(); 139 DefaultSyntaxKit.initKit();
148 m_sourceReader = new CodeReader(); 140 sourceReader = new CodeReader();
149 m_sourceReader.setSelectionListener(new CodeReader.SelectionListener() { 141 sourceReader.setSelectionListener(reference ->
150 @Override 142 {
151 public void onSelect(EntryReference<Entry, Entry> reference) { 143 if (reference != null) {
152 if (reference != null) { 144 onSelectSource(reference.entry);
153 onSelectSource(reference.entry); 145 } else {
154 } else { 146 onSelectSource(null);
155 onSelectSource(null);
156 }
157 } 147 }
158 }); 148 });
159 m_destReader = new CodeReader(); 149 destReader = new CodeReader();
160 m_destReader.setSelectionListener(new CodeReader.SelectionListener() { 150 destReader.setSelectionListener(reference ->
161 @Override 151 {
162 public void onSelect(EntryReference<Entry, Entry> reference) { 152 if (reference != null) {
163 if (reference != null) { 153 onSelectDest(reference.entry);
164 onSelectDest(reference.entry); 154 } else {
165 } else { 155 onSelectDest(null);
166 onSelectDest(null);
167 }
168 } 156 }
169 }); 157 });
170 158
@@ -173,14 +161,15 @@ public class MemberMatchingGui<T extends Entry> {
173 @Override 161 @Override
174 public void keyPressed(KeyEvent event) { 162 public void keyPressed(KeyEvent event) {
175 if (event.getKeyCode() == KeyEvent.VK_M) 163 if (event.getKeyCode() == KeyEvent.VK_M)
176 m_matchButton.doClick(); 164 matchButton.doClick();
177 } 165 }
178 }; 166 };
179 m_sourceReader.addKeyListener(keyListener); 167 sourceReader.addKeyListener(keyListener);
180 m_destReader.addKeyListener(keyListener); 168 destReader.addKeyListener(keyListener);
181 169
182 // init all the splits 170 // init all the splits
183 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(m_sourceReader), new JScrollPane(m_destReader)); 171 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(sourceReader), new JScrollPane(
172 destReader));
184 splitRight.setResizeWeight(0.5); // resize 50:50 173 splitRight.setResizeWeight(0.5); // resize 50:50
185 JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, classesPanel, splitRight); 174 JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, classesPanel, splitRight);
186 splitLeft.setResizeWeight(0); // let the right side take all the slack 175 splitLeft.setResizeWeight(0); // let the right side take all the slack
@@ -192,102 +181,92 @@ public class MemberMatchingGui<T extends Entry> {
192 bottomPanel.setLayout(new FlowLayout()); 181 bottomPanel.setLayout(new FlowLayout());
193 pane.add(bottomPanel, BorderLayout.SOUTH); 182 pane.add(bottomPanel, BorderLayout.SOUTH);
194 183
195 m_matchButton = new JButton(); 184 matchButton = new JButton();
196 m_unmatchableButton = new JButton(); 185 unmatchableButton = new JButton();
197 186
198 m_sourceLabel = new JLabel(); 187 sourceLabel = new JLabel();
199 bottomPanel.add(m_sourceLabel); 188 bottomPanel.add(sourceLabel);
200 bottomPanel.add(m_matchButton); 189 bottomPanel.add(matchButton);
201 bottomPanel.add(m_unmatchableButton); 190 bottomPanel.add(unmatchableButton);
202 m_destLabel = new JLabel(); 191 destLabel = new JLabel();
203 bottomPanel.add(m_destLabel); 192 bottomPanel.add(destLabel);
204 193
205 // show the frame 194 // show the frame
206 pane.doLayout(); 195 pane.doLayout();
207 m_frame.setSize(1024, 576); 196 frame.setSize(1024, 576);
208 m_frame.setMinimumSize(new Dimension(640, 480)); 197 frame.setMinimumSize(new Dimension(640, 480));
209 m_frame.setVisible(true); 198 frame.setVisible(true);
210 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 199 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
211 200
212 m_unmatchedHighlightPainter = new ObfuscatedHighlightPainter(); 201 unmatchedHighlightPainter = new ObfuscatedHighlightPainter();
213 m_matchedHighlightPainter = new DeobfuscatedHighlightPainter(); 202 matchedHighlightPainter = new DeobfuscatedHighlightPainter();
214 203
215 // init state 204 // init state
216 m_saveListener = null; 205 saveListener = null;
217 m_obfSourceClass = null; 206 obfSourceClass = null;
218 m_obfDestClass = null; 207 obfDestClass = null;
219 m_obfSourceEntry = null; 208 obfSourceEntry = null;
220 m_obfDestEntry = null; 209 obfDestEntry = null;
221 setSourceType(SourceType.getDefault()); 210 setSourceType(SourceType.getDefault());
222 updateButtons(); 211 updateButtons();
223 } 212 }
224 213
225 protected void setSourceType(SourceType val) { 214 protected void setSourceType(SourceType val) {
226 m_sourceType = val; 215 sourceType = val;
227 updateSourceClasses(); 216 updateSourceClasses();
228 } 217 }
229 218
230 public void setSaveListener(SaveListener<T> val) { 219 public void setSaveListener(SaveListener<T> val) {
231 m_saveListener = val; 220 saveListener = val;
232 } 221 }
233 222
234 private void updateSourceClasses() { 223 private void updateSourceClasses() {
235 224
236 String selectedPackage = m_sourceClasses.getSelectedPackage(); 225 String selectedPackage = sourceClasses.getSelectedPackage();
237 226
238 List<ClassEntry> deobfClassEntries = Lists.newArrayList(); 227 List<ClassEntry> deobfClassEntries = Lists.newArrayList();
239 for (ClassEntry entry : m_sourceType.getObfSourceClasses(m_memberMatches)) { 228 for (ClassEntry entry : sourceType.getObfSourceClasses(memberMatches)) {
240 deobfClassEntries.add(m_sourceDeobfuscator.deobfuscateEntry(entry)); 229 deobfClassEntries.add(sourceDeobfuscator.deobfuscateEntry(entry));
241 } 230 }
242 m_sourceClasses.setClasses(deobfClassEntries); 231 sourceClasses.setClasses(deobfClassEntries);
243 232
244 if (selectedPackage != null) { 233 if (selectedPackage != null) {
245 m_sourceClasses.expandPackage(selectedPackage); 234 sourceClasses.expandPackage(selectedPackage);
246 } 235 }
247 236
248 for (SourceType sourceType : SourceType.values()) { 237 for (SourceType sourceType : SourceType.values()) {
249 m_sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)", 238 sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)",
250 sourceType.name(), sourceType.getObfSourceClasses(m_memberMatches).size() 239 sourceType.name(), sourceType.getObfSourceClasses(memberMatches).size()
251 )); 240 ));
252 } 241 }
253 } 242 }
254 243
255 protected void setSourceClass(ClassEntry sourceClass) { 244 protected void setSourceClass(ClassEntry sourceClass) {
256 245
257 m_obfSourceClass = m_sourceDeobfuscator.obfuscateEntry(sourceClass); 246 obfSourceClass = sourceDeobfuscator.obfuscateEntry(sourceClass);
258 m_obfDestClass = m_classMatches.getUniqueMatches().get(m_obfSourceClass); 247 obfDestClass = classMatches.getUniqueMatches().get(obfSourceClass);
259 if (m_obfDestClass == null) { 248 if (obfDestClass == null) {
260 throw new Error("No matching dest class for source class: " + m_obfSourceClass); 249 throw new Error("No matching dest class for source class: " + obfSourceClass);
261 } 250 }
262 251
263 m_sourceReader.decompileClass(m_obfSourceClass, m_sourceDeobfuscator, false, new Runnable() { 252 sourceReader.decompileClass(obfSourceClass, sourceDeobfuscator, false, this::updateSourceHighlights);
264 @Override 253 destReader.decompileClass(obfDestClass, destDeobfuscator, false, this::updateDestHighlights);
265 public void run() {
266 updateSourceHighlights();
267 }
268 });
269 m_destReader.decompileClass(m_obfDestClass, m_destDeobfuscator, false, new Runnable() {
270 @Override
271 public void run() {
272 updateDestHighlights();
273 }
274 });
275 } 254 }
276 255
277 protected void updateSourceHighlights() { 256 protected void updateSourceHighlights() {
278 highlightEntries(m_sourceReader, m_sourceDeobfuscator, m_memberMatches.matches().keySet(), m_memberMatches.getUnmatchedSourceEntries()); 257 highlightEntries(sourceReader, sourceDeobfuscator, memberMatches.matches().keySet(), memberMatches.getUnmatchedSourceEntries());
279 } 258 }
280 259
281 protected void updateDestHighlights() { 260 protected void updateDestHighlights() {
282 highlightEntries(m_destReader, m_destDeobfuscator, m_memberMatches.matches().values(), m_memberMatches.getUnmatchedDestEntries()); 261 highlightEntries(destReader, destDeobfuscator, memberMatches.matches().values(), memberMatches.getUnmatchedDestEntries());
283 } 262 }
284 263
285 private void highlightEntries(CodeReader reader, Deobfuscator deobfuscator, Collection<T> obfMatchedEntries, Collection<T> obfUnmatchedEntries) { 264 private void highlightEntries(CodeReader reader, Deobfuscator deobfuscator, Collection<T> obfMatchedEntries, Collection<T> obfUnmatchedEntries) {
286 reader.clearHighlights(); 265 reader.clearHighlights();
287 // matched fields 266 // matched fields
288 updateHighlighted(obfMatchedEntries, deobfuscator, reader, m_matchedHighlightPainter); 267 updateHighlighted(obfMatchedEntries, deobfuscator, reader, matchedHighlightPainter);
289 // unmatched fields 268 // unmatched fields
290 updateHighlighted(obfUnmatchedEntries, deobfuscator, reader, m_unmatchedHighlightPainter); 269 updateHighlighted(obfUnmatchedEntries, deobfuscator, reader, unmatchedHighlightPainter);
291 } 270 }
292 271
293 private void updateHighlighted(Collection<T> entries, Deobfuscator deobfuscator, CodeReader reader, HighlightPainter painter) 272 private void updateHighlighted(Collection<T> entries, Deobfuscator deobfuscator, CodeReader reader, HighlightPainter painter)
@@ -303,8 +282,8 @@ public class MemberMatchingGui<T extends Entry> {
303 } 282 }
304 283
305 private boolean isSelectionMatched() { 284 private boolean isSelectionMatched() {
306 return m_obfSourceEntry != null && m_obfDestEntry != null 285 return obfSourceEntry != null && obfDestEntry != null
307 && m_memberMatches.isMatched(m_obfSourceEntry, m_obfDestEntry); 286 && memberMatches.isMatched(obfSourceEntry, obfDestEntry);
308 } 287 }
309 288
310 protected void onSelectSource(Entry source) { 289 protected void onSelectSource(Entry source) {
@@ -324,12 +303,12 @@ public class MemberMatchingGui<T extends Entry> {
324 @SuppressWarnings("unchecked") 303 @SuppressWarnings("unchecked")
325 T sourceEntry = (T) source; 304 T sourceEntry = (T) source;
326 305
327 T obfSourceEntry = m_sourceDeobfuscator.obfuscateEntry(sourceEntry); 306 T obfSourceEntry = sourceDeobfuscator.obfuscateEntry(sourceEntry);
328 if (m_memberMatches.hasSource(obfSourceEntry)) { 307 if (memberMatches.hasSource(obfSourceEntry)) {
329 setSource(obfSourceEntry); 308 setSource(obfSourceEntry);
330 309
331 // look for a matched dest too 310 // look for a matched dest too
332 T obfDestEntry = m_memberMatches.matches().get(obfSourceEntry); 311 T obfDestEntry = memberMatches.matches().get(obfSourceEntry);
333 if (obfDestEntry != null) { 312 if (obfDestEntry != null) {
334 setDest(obfDestEntry); 313 setDest(obfDestEntry);
335 } 314 }
@@ -356,12 +335,12 @@ public class MemberMatchingGui<T extends Entry> {
356 @SuppressWarnings("unchecked") 335 @SuppressWarnings("unchecked")
357 T destEntry = (T) dest; 336 T destEntry = (T) dest;
358 337
359 T obfDestEntry = m_destDeobfuscator.obfuscateEntry(destEntry); 338 T obfDestEntry = destDeobfuscator.obfuscateEntry(destEntry);
360 if (m_memberMatches.hasDest(obfDestEntry)) { 339 if (memberMatches.hasDest(obfDestEntry)) {
361 setDest(obfDestEntry); 340 setDest(obfDestEntry);
362 341
363 // look for a matched source too 342 // look for a matched source too
364 T obfSourceEntry = m_memberMatches.matches().inverse().get(obfDestEntry); 343 T obfSourceEntry = memberMatches.matches().inverse().get(obfDestEntry);
365 if (obfSourceEntry != null) { 344 if (obfSourceEntry != null) {
366 setSource(obfSourceEntry); 345 setSource(obfSourceEntry);
367 } 346 }
@@ -373,21 +352,21 @@ public class MemberMatchingGui<T extends Entry> {
373 352
374 private void setSource(T obfEntry) { 353 private void setSource(T obfEntry) {
375 if (obfEntry == null) { 354 if (obfEntry == null) {
376 m_obfSourceEntry = null; 355 obfSourceEntry = null;
377 m_sourceLabel.setText(""); 356 sourceLabel.setText("");
378 } else { 357 } else {
379 m_obfSourceEntry = obfEntry; 358 obfSourceEntry = obfEntry;
380 m_sourceLabel.setText(getEntryLabel(obfEntry, m_sourceDeobfuscator)); 359 sourceLabel.setText(getEntryLabel(obfEntry, sourceDeobfuscator));
381 } 360 }
382 } 361 }
383 362
384 private void setDest(T obfEntry) { 363 private void setDest(T obfEntry) {
385 if (obfEntry == null) { 364 if (obfEntry == null) {
386 m_obfDestEntry = null; 365 obfDestEntry = null;
387 m_destLabel.setText(""); 366 destLabel.setText("");
388 } else { 367 } else {
389 m_obfDestEntry = obfEntry; 368 obfDestEntry = obfEntry;
390 m_destLabel.setText(getEntryLabel(obfEntry, m_destDeobfuscator)); 369 destLabel.setText(getEntryLabel(obfEntry, destDeobfuscator));
391 } 370 }
392 } 371 }
393 372
@@ -399,39 +378,23 @@ public class MemberMatchingGui<T extends Entry> {
399 378
400 private void updateButtons() { 379 private void updateButtons() {
401 380
402 GuiTricks.deactivateButton(m_matchButton); 381 GuiTricks.deactivateButton(matchButton);
403 GuiTricks.deactivateButton(m_unmatchableButton); 382 GuiTricks.deactivateButton(unmatchableButton);
404 383
405 if (m_obfSourceEntry != null && m_obfDestEntry != null) { 384 if (obfSourceEntry != null && obfDestEntry != null) {
406 if (m_memberMatches.isMatched(m_obfSourceEntry, m_obfDestEntry)) { 385 if (memberMatches.isMatched(obfSourceEntry, obfDestEntry))
407 GuiTricks.activateButton(m_matchButton, "Unmatch", new ActionListener() { 386 GuiTricks.activateButton(matchButton, "Unmatch", event -> unmatch());
408 @Override 387 else if (!memberMatches.isMatchedSourceEntry(obfSourceEntry) && !memberMatches.isMatchedDestEntry(
409 public void actionPerformed(ActionEvent event) { 388 obfDestEntry))
410 unmatch(); 389 GuiTricks.activateButton(matchButton, "Match", event -> match());
411 } 390 } else if (obfSourceEntry != null)
412 }); 391 GuiTricks.activateButton(unmatchableButton, "Set Unmatchable", event -> unmatchable());
413 } else if (!m_memberMatches.isMatchedSourceEntry(m_obfSourceEntry) && !m_memberMatches.isMatchedDestEntry(m_obfDestEntry)) {
414 GuiTricks.activateButton(m_matchButton, "Match", new ActionListener() {
415 @Override
416 public void actionPerformed(ActionEvent event) {
417 match();
418 }
419 });
420 }
421 } else if (m_obfSourceEntry != null) {
422 GuiTricks.activateButton(m_unmatchableButton, "Set Unmatchable", new ActionListener() {
423 @Override
424 public void actionPerformed(ActionEvent event) {
425 unmatchable();
426 }
427 });
428 }
429 } 392 }
430 393
431 protected void match() { 394 protected void match() {
432 395
433 // update the field matches 396 // update the field matches
434 m_memberMatches.makeMatch(m_obfSourceEntry, m_obfDestEntry, m_sourceDeobfuscator, m_destDeobfuscator); 397 memberMatches.makeMatch(obfSourceEntry, obfDestEntry, sourceDeobfuscator, destDeobfuscator);
435 save(); 398 save();
436 399
437 // update the ui 400 // update the ui
@@ -445,7 +408,7 @@ public class MemberMatchingGui<T extends Entry> {
445 protected void unmatch() { 408 protected void unmatch() {
446 409
447 // update the field matches 410 // update the field matches
448 m_memberMatches.unmakeMatch(m_obfSourceEntry, m_obfDestEntry, m_sourceDeobfuscator, m_destDeobfuscator); 411 memberMatches.unmakeMatch(obfSourceEntry, obfDestEntry, sourceDeobfuscator, destDeobfuscator);
449 save(); 412 save();
450 413
451 // update the ui 414 // update the ui
@@ -459,7 +422,7 @@ public class MemberMatchingGui<T extends Entry> {
459 protected void unmatchable() { 422 protected void unmatchable() {
460 423
461 // update the field matches 424 // update the field matches
462 m_memberMatches.makeSourceUnmatchable(m_obfSourceEntry, m_sourceDeobfuscator); 425 memberMatches.makeSourceUnmatchable(obfSourceEntry, sourceDeobfuscator);
463 save(); 426 save();
464 427
465 // update the ui 428 // update the ui
@@ -471,8 +434,8 @@ public class MemberMatchingGui<T extends Entry> {
471 } 434 }
472 435
473 private void save() { 436 private void save() {
474 if (m_saveListener != null) { 437 if (saveListener != null) {
475 m_saveListener.save(m_memberMatches); 438 saveListener.save(memberMatches);
476 } 439 }
477 } 440 }
478} 441}
diff --git a/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java b/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java
index d1e2de0..bd9fe3d 100644
--- a/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java
+++ b/src/main/java/cuchaz/enigma/gui/ScoredClassEntry.java
@@ -17,14 +17,28 @@ public class ScoredClassEntry extends ClassEntry {
17 17
18 private static final long serialVersionUID = -8798725308554217105L; 18 private static final long serialVersionUID = -8798725308554217105L;
19 19
20 private float m_score; 20 private float score;
21 21
22 public ScoredClassEntry(ClassEntry other, float score) { 22 public ScoredClassEntry(ClassEntry other, float score) {
23 super(other); 23 super(other);
24 m_score = score; 24 this.score = score;
25 } 25 }
26 26
27 public float getScore() { 27 public float getScore() {
28 return m_score; 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 && score == other.score;
29 } 43 }
30} 44}
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java
index 8d3df47..5c1d9ff 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java
@@ -23,15 +23,15 @@ import cuchaz.enigma.utils.Utils;
23 23
24public class CrashDialog { 24public class CrashDialog {
25 25
26 private static CrashDialog m_instance = null; 26 private static CrashDialog instance = null;
27 27
28 private JFrame m_frame; 28 private JFrame frame;
29 private JTextArea m_text; 29 private JTextArea text;
30 30
31 private CrashDialog(JFrame parent) { 31 private CrashDialog(JFrame parent) {
32 // init frame 32 // init frame
33 m_frame = new JFrame(Constants.NAME + " - Crash Report"); 33 frame = new JFrame(Constants.NAME + " - Crash Report");
34 final Container pane = m_frame.getContentPane(); 34 final Container pane = frame.getContentPane();
35 pane.setLayout(new BorderLayout()); 35 pane.setLayout(new BorderLayout());
36 36
37 JLabel label = new JLabel(Constants.NAME + " has crashed! =("); 37 JLabel label = new JLabel(Constants.NAME + " has crashed! =(");
@@ -39,9 +39,9 @@ public class CrashDialog {
39 pane.add(label, BorderLayout.NORTH); 39 pane.add(label, BorderLayout.NORTH);
40 40
41 // report panel 41 // report panel
42 m_text = new JTextArea(); 42 text = new JTextArea();
43 m_text.setTabSize(2); 43 text.setTabSize(2);
44 pane.add(new JScrollPane(m_text), BorderLayout.CENTER); 44 pane.add(new JScrollPane(text), BorderLayout.CENTER);
45 45
46 // buttons panel 46 // buttons panel
47 JPanel buttonsPanel = new JPanel(); 47 JPanel buttonsPanel = new JPanel();
@@ -52,7 +52,7 @@ public class CrashDialog {
52 JButton ignoreButton = new JButton("Ignore"); 52 JButton ignoreButton = new JButton("Ignore");
53 ignoreButton.addActionListener(event -> { 53 ignoreButton.addActionListener(event -> {
54 // close (hide) the dialog 54 // close (hide) the dialog
55 m_frame.setVisible(false); 55 frame.setVisible(false);
56 }); 56 });
57 buttonsPanel.add(ignoreButton); 57 buttonsPanel.add(ignoreButton);
58 JButton exitButton = new JButton("Exit"); 58 JButton exitButton = new JButton("Exit");
@@ -64,13 +64,13 @@ public class CrashDialog {
64 pane.add(buttonsPanel, BorderLayout.SOUTH); 64 pane.add(buttonsPanel, BorderLayout.SOUTH);
65 65
66 // show the frame 66 // show the frame
67 m_frame.setSize(600, 400); 67 frame.setSize(600, 400);
68 m_frame.setLocationRelativeTo(parent); 68 frame.setLocationRelativeTo(parent);
69 m_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 69 frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
70 } 70 }
71 71
72 public static void init(JFrame parent) { 72 public static void init(JFrame parent) {
73 m_instance = new CrashDialog(parent); 73 instance = new CrashDialog(parent);
74 } 74 }
75 75
76 public static void show(Throwable ex) { 76 public static void show(Throwable ex) {
@@ -80,8 +80,8 @@ public class CrashDialog {
80 String report = buf.toString(); 80 String report = buf.toString();
81 81
82 // show it! 82 // show it!
83 m_instance.m_text.setText(report); 83 instance.text.setText(report);
84 m_instance.m_frame.doLayout(); 84 instance.frame.doLayout();
85 m_instance.m_frame.setVisible(true); 85 instance.frame.setVisible(true);
86 } 86 }
87} 87}
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
index c752c86..8df22a7 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
@@ -87,15 +87,13 @@ public class ProgressDialog implements ProgressListener, AutoCloseable {
87 } 87 }
88 88
89 public static void runInThread(final JFrame parent, final ProgressRunnable runnable) { 89 public static void runInThread(final JFrame parent, final ProgressRunnable runnable) {
90 new Thread() { 90 new Thread(() ->
91 @Override 91 {
92 public void run() { 92 try (ProgressDialog progress = new ProgressDialog(parent)) {
93 try (ProgressDialog progress = new ProgressDialog(parent)) { 93 runnable.run(progress);
94 runnable.run(progress); 94 } catch (Exception ex) {
95 } catch (Exception ex) { 95 throw new Error(ex);
96 throw new Error(ex);
97 }
98 } 96 }
99 }.start(); 97 }).start();
100 } 98 }
101} 99}
diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
index dcd7c93..0ccd537 100644
--- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
+++ b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
@@ -42,16 +42,14 @@ public class MenuBar extends JMenuBar {
42 item.addActionListener(event -> { 42 item.addActionListener(event -> {
43 if (this.gui.jarFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { 43 if (this.gui.jarFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) {
44 // load the jar in a separate thread 44 // load the jar in a separate thread
45 new Thread() { 45 new Thread(() ->
46 @Override 46 {
47 public void run() { 47 try {
48 try { 48 gui.getController().openJar(new JarFile(gui.jarFileChooser.getSelectedFile()));
49 gui.getController().openJar(new JarFile(gui.jarFileChooser.getSelectedFile())); 49 } catch (IOException ex) {
50 } catch (IOException ex) { 50 throw new Error(ex);
51 throw new Error(ex);
52 }
53 } 51 }
54 }.start(); 52 }).start();
55 } 53 }
56 }); 54 });
57 } 55 }
@@ -177,9 +175,7 @@ public class MenuBar extends JMenuBar {
177 { 175 {
178 JMenuItem item = new JMenuItem("Rebuild Method Names"); 176 JMenuItem item = new JMenuItem("Rebuild Method Names");
179 menu.add(item); 177 menu.add(item);
180 item.addActionListener(event -> { 178 item.addActionListener(event -> this.gui.getController().rebuildMethodNames());
181 this.gui.getController().rebuildMethodNames();
182 });
183 this.rebuildMethodNamesMenu = item; 179 this.rebuildMethodNamesMenu = item;
184 } 180 }
185 menu.addSeparator(); 181 menu.addSeparator();
diff --git a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java
index 2b06342..e387ed3 100644
--- a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java
+++ b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java
@@ -53,7 +53,7 @@ public class PopupMenuBar extends JPopupMenu {
53 } 53 }
54 { 54 {
55 JMenuItem menu = new JMenuItem("Go to Declaration"); 55 JMenuItem menu = new JMenuItem("Go to Declaration");
56 menu.addActionListener(event -> gui.navigateTo(gui.m_reference.entry)); 56 menu.addActionListener(event -> gui.navigateTo(gui.reference.entry));
57 menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0)); 57 menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0));
58 menu.setEnabled(false); 58 menu.setEnabled(false);
59 this.add(menu); 59 this.add(menu);
diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java
index 8341826..9f391f2 100644
--- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java
+++ b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java
@@ -37,6 +37,11 @@ public class ClassSelectorClassNode extends DefaultMutableTreeNode {
37 return other instanceof ClassSelectorClassNode && equals((ClassSelectorClassNode) other); 37 return other instanceof ClassSelectorClassNode && equals((ClassSelectorClassNode) other);
38 } 38 }
39 39
40 @Override public int hashCode()
41 {
42 return 17 + (classEntry != null ? classEntry.hashCode() : 0);
43 }
44
40 @Override public void setUserObject(Object userObject) 45 @Override public void setUserObject(Object userObject)
41 { 46 {
42 String packageName = ""; 47 String packageName = "";
diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java
index 31b4ebf..b3eb90e 100644
--- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java
+++ b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java
@@ -48,6 +48,11 @@ public class ClassSelectorPackageNode extends DefaultMutableTreeNode {
48 return other instanceof ClassSelectorPackageNode && equals((ClassSelectorPackageNode) other); 48 return other instanceof ClassSelectorPackageNode && equals((ClassSelectorPackageNode) other);
49 } 49 }
50 50
51 @Override public int hashCode()
52 {
53 return packageName.hashCode();
54 }
55
51 public boolean equals(ClassSelectorPackageNode other) { 56 public boolean equals(ClassSelectorPackageNode other) {
52 return other != null && this.packageName.equals(other.packageName); 57 return other != null && this.packageName.equals(other.packageName);
53 } 58 }