summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java')
-rw-r--r--src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java290
1 files changed, 141 insertions, 149 deletions
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}