summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/gui/FieldMatchingGui.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/gui/FieldMatchingGui.java')
-rw-r--r--src/cuchaz/enigma/gui/FieldMatchingGui.java212
1 files changed, 185 insertions, 27 deletions
diff --git a/src/cuchaz/enigma/gui/FieldMatchingGui.java b/src/cuchaz/enigma/gui/FieldMatchingGui.java
index de9ba14..ef374c8 100644
--- a/src/cuchaz/enigma/gui/FieldMatchingGui.java
+++ b/src/cuchaz/enigma/gui/FieldMatchingGui.java
@@ -4,24 +4,34 @@ import java.awt.BorderLayout;
4import java.awt.Container; 4import java.awt.Container;
5import java.awt.Dimension; 5import java.awt.Dimension;
6import java.awt.FlowLayout; 6import java.awt.FlowLayout;
7import java.util.Map; 7import java.awt.event.ActionEvent;
8import java.awt.event.ActionListener;
9import java.util.Collection;
10import java.util.Set;
8 11
9import javax.swing.BoxLayout; 12import javax.swing.BoxLayout;
13import javax.swing.JButton;
10import javax.swing.JFrame; 14import javax.swing.JFrame;
11import javax.swing.JLabel; 15import javax.swing.JLabel;
12import javax.swing.JPanel; 16import javax.swing.JPanel;
13import javax.swing.JScrollPane; 17import javax.swing.JScrollPane;
14import javax.swing.JSplitPane; 18import javax.swing.JSplitPane;
15import javax.swing.WindowConstants; 19import javax.swing.WindowConstants;
20import javax.swing.text.Highlighter.HighlightPainter;
21
22import com.google.common.collect.Sets;
16 23
17import cuchaz.enigma.Constants; 24import cuchaz.enigma.Constants;
18import cuchaz.enigma.Deobfuscator; 25import cuchaz.enigma.Deobfuscator;
26import cuchaz.enigma.analysis.EntryReference;
27import cuchaz.enigma.analysis.SourceIndex;
28import cuchaz.enigma.analysis.Token;
19import cuchaz.enigma.convert.ClassMatches; 29import cuchaz.enigma.convert.ClassMatches;
20import cuchaz.enigma.convert.FieldMatches; 30import cuchaz.enigma.convert.FieldMatches;
21import cuchaz.enigma.gui.ClassSelector.ClassSelectionListener; 31import cuchaz.enigma.gui.ClassSelector.ClassSelectionListener;
22import cuchaz.enigma.mapping.ClassEntry; 32import cuchaz.enigma.mapping.ClassEntry;
33import cuchaz.enigma.mapping.Entry;
23import cuchaz.enigma.mapping.FieldEntry; 34import cuchaz.enigma.mapping.FieldEntry;
24import cuchaz.enigma.mapping.FieldMapping;
25import de.sciss.syntaxpane.DefaultSyntaxKit; 35import de.sciss.syntaxpane.DefaultSyntaxKit;
26 36
27 37
@@ -36,19 +46,28 @@ public class FieldMatchingGui {
36 private ClassSelector m_sourceClasses; 46 private ClassSelector m_sourceClasses;
37 private CodeReader m_sourceReader; 47 private CodeReader m_sourceReader;
38 private CodeReader m_destReader; 48 private CodeReader m_destReader;
49 private JButton m_matchButton;
50 private JLabel m_sourceLabel;
51 private JLabel m_destLabel;
52 private HighlightPainter m_unmatchedHighlightPainter;
53 private HighlightPainter m_matchedHighlightPainter;
39 54
40 private ClassMatches m_classMatches; 55 private ClassMatches m_classMatches;
41 private FieldMatches m_fieldMatches; 56 private FieldMatches m_fieldMatches;
42 private Map<FieldEntry,FieldMapping> m_droppedFieldMappings;
43 private Deobfuscator m_sourceDeobfuscator; 57 private Deobfuscator m_sourceDeobfuscator;
44 private Deobfuscator m_destDeobfuscator; 58 private Deobfuscator m_destDeobfuscator;
45 private SaveListener m_saveListener; 59 private SaveListener m_saveListener;
60 private ClassEntry m_obfSourceClass;
61 private ClassEntry m_obfDestClass;
62 private FieldEntry m_obfSourceField;
63 private FieldEntry m_obfDestField;
64 private Set<FieldEntry> m_obfUnmatchedSourceFields;
65 private Set<FieldEntry> m_obfUnmatchedDestFields;
46 66
47 public FieldMatchingGui(ClassMatches classMatches, FieldMatches fieldMatches, Map<FieldEntry,FieldMapping> droppedFieldMappings, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) { 67 public FieldMatchingGui(ClassMatches classMatches, FieldMatches fieldMatches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) {
48 68
49 m_classMatches = classMatches; 69 m_classMatches = classMatches;
50 m_fieldMatches = fieldMatches; 70 m_fieldMatches = fieldMatches;
51 m_droppedFieldMappings = droppedFieldMappings;
52 m_sourceDeobfuscator = sourceDeobfuscator; 71 m_sourceDeobfuscator = sourceDeobfuscator;
53 m_destDeobfuscator = destDeobfuscator; 72 m_destDeobfuscator = destDeobfuscator;
54 73
@@ -74,31 +93,57 @@ public class FieldMatchingGui {
74 JScrollPane sourceScroller = new JScrollPane(m_sourceClasses); 93 JScrollPane sourceScroller = new JScrollPane(m_sourceClasses);
75 classesPanel.add(sourceScroller); 94 classesPanel.add(sourceScroller);
76 95
77 // init fields side
78 JPanel fieldsPanel = new JPanel();
79 fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.PAGE_AXIS));
80 fieldsPanel.setPreferredSize(new Dimension(200, 0));
81 pane.add(fieldsPanel, BorderLayout.WEST);
82 fieldsPanel.add(new JLabel("Destination Fields"));
83
84 // init readers 96 // init readers
85 DefaultSyntaxKit.initKit(); 97 DefaultSyntaxKit.initKit();
86 m_sourceReader = new CodeReader(); 98 m_sourceReader = new CodeReader();
99 m_sourceReader.setSelectionListener(new CodeReader.SelectionListener() {
100 @Override
101 public void onSelect(EntryReference<Entry,Entry> reference) {
102 if (reference != null) {
103 onSelectSource(reference.entry);
104 } else {
105 onSelectSource(null);
106 }
107 }
108 });
87 m_destReader = new CodeReader(); 109 m_destReader = new CodeReader();
110 m_destReader.setSelectionListener(new CodeReader.SelectionListener() {
111 @Override
112 public void onSelect(EntryReference<Entry,Entry> reference) {
113 if (reference != null) {
114 onSelectDest(reference.entry);
115 } else {
116 onSelectDest(null);
117 }
118 }
119 });
88 120
89 // init all the splits 121 // init all the splits
90 JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, classesPanel, new JScrollPane(m_sourceReader)); 122 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(m_sourceReader), new JScrollPane(m_destReader));
123 splitRight.setResizeWeight(0.5); // resize 50:50
124 JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, classesPanel, splitRight);
91 splitLeft.setResizeWeight(0); // let the right side take all the slack 125 splitLeft.setResizeWeight(0); // let the right side take all the slack
92 JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(m_destReader), fieldsPanel); 126 pane.add(splitLeft, BorderLayout.CENTER);
93 splitRight.setResizeWeight(1); // let the left side take all the slack 127 splitLeft.resetToPreferredSizes();
94 JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, splitRight);
95 splitCenter.setResizeWeight(0.5); // resize 50:50
96 pane.add(splitCenter, BorderLayout.CENTER);
97 splitCenter.resetToPreferredSizes();
98 128
99 // init bottom panel 129 // init bottom panel
100 JPanel bottomPanel = new JPanel(); 130 JPanel bottomPanel = new JPanel();
101 bottomPanel.setLayout(new FlowLayout()); 131 bottomPanel.setLayout(new FlowLayout());
132 pane.add(bottomPanel, BorderLayout.SOUTH);
133
134 m_matchButton = new JButton("Match");
135 m_matchButton.addActionListener(new ActionListener() {
136 @Override
137 public void actionPerformed(ActionEvent event) {
138 match();
139 }
140 });
141
142 m_sourceLabel = new JLabel();
143 bottomPanel.add(m_sourceLabel);
144 bottomPanel.add(m_matchButton);
145 m_destLabel = new JLabel();
146 bottomPanel.add(m_destLabel);
102 147
103 // show the frame 148 // show the frame
104 pane.doLayout(); 149 pane.doLayout();
@@ -106,26 +151,139 @@ public class FieldMatchingGui {
106 m_frame.setMinimumSize(new Dimension(640, 480)); 151 m_frame.setMinimumSize(new Dimension(640, 480));
107 m_frame.setVisible(true); 152 m_frame.setVisible(true);
108 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 153 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
154
155 m_unmatchedHighlightPainter = new ObfuscatedHighlightPainter();
156 m_matchedHighlightPainter = new DeobfuscatedHighlightPainter();
109 157
110 // init state 158 // init state
111 m_saveListener = null; 159 m_saveListener = null;
112 m_fieldMatches.addUnmatchedSourceFields(droppedFieldMappings.keySet()); 160 m_obfSourceClass = null;
113 m_sourceClasses.setClasses(m_fieldMatches.getSourceClassesWithUnmatchedFields()); 161 m_obfDestClass = null;
162 m_obfSourceField = null;
163 m_obfDestField = null;
164 m_obfUnmatchedSourceFields = null;
165 m_obfUnmatchedDestFields = null;
166 updateSourceClasses();
167 updateMatchButton();
114 } 168 }
115 169
116 public void setSaveListener(SaveListener val) { 170 public void setSaveListener(SaveListener val) {
117 m_saveListener = val; 171 m_saveListener = val;
118 } 172 }
119 173
174 private void updateSourceClasses() {
175 m_sourceClasses.setClasses(m_fieldMatches.getSourceClassesWithUnmatchedFields());
176 m_sourceClasses.expandAll();
177 }
178
120 protected void setSourceClass(ClassEntry obfSourceClass) { 179 protected void setSourceClass(ClassEntry obfSourceClass) {
121 180
122 // get the matched dest class 181 m_obfSourceClass = obfSourceClass;
123 final ClassEntry obfDestClass = m_classMatches.getUniqueMatches().get(obfSourceClass); 182 m_obfDestClass = m_classMatches.getUniqueMatches().get(obfSourceClass);
124 if (obfDestClass == null) { 183 if (m_obfDestClass == null) {
125 throw new Error("No matching dest class for source class: " + obfSourceClass); 184 throw new Error("No matching dest class for source class: " + m_obfSourceClass);
126 } 185 }
186
187 updateUnmatchedFields();
188 m_sourceReader.decompileClass(m_obfSourceClass, m_sourceDeobfuscator, new Runnable() {
189 @Override
190 public void run() {
191 updateSourceHighlights();
192 }
193 });
194 m_destReader.decompileClass(m_obfDestClass, m_destDeobfuscator, new Runnable() {
195 @Override
196 public void run() {
197 updateDestHighlights();
198 }
199 });
200 }
201
202 private void updateUnmatchedFields() {
203 m_obfUnmatchedSourceFields = Sets.newHashSet(m_fieldMatches.getUnmatchedSourceFields(m_obfSourceClass));
204 m_obfUnmatchedDestFields = Sets.newHashSet();
205 for (FieldEntry destFieldEntry : m_destDeobfuscator.getJarIndex().getObfFieldEntries(m_obfDestClass)) {
206 if (!m_fieldMatches.isDestMatched(destFieldEntry)) {
207 m_obfUnmatchedDestFields.add(destFieldEntry);
208 }
209 }
210 }
211
212 protected void updateSourceHighlights() {
213 highlightFields(m_sourceReader, m_sourceDeobfuscator, m_obfUnmatchedSourceFields, m_fieldMatches.matches().keySet());
214 }
215
216 protected void updateDestHighlights() {
217 highlightFields(m_destReader, m_destDeobfuscator, m_obfUnmatchedDestFields, m_fieldMatches.matches().values());
218 }
219
220 private void highlightFields(CodeReader reader, Deobfuscator deobfuscator, Collection<FieldEntry> obfFieldEntries, Collection<FieldEntry> obfMatchedFieldEntries) {
221 reader.clearHighlights();
222 SourceIndex index = reader.getSourceIndex();
223 for (FieldEntry obfFieldEntry : obfFieldEntries) {
224 FieldEntry deobfFieldEntry = deobfuscator.deobfuscateEntry(obfFieldEntry);
225 Token token = index.getDeclarationToken(deobfFieldEntry);
226 if (token == null) {
227 System.err.println("WARNING: Can't find declaration token for " + deobfFieldEntry);
228 } else {
229 reader.setHighlightedToken(
230 token,
231 obfMatchedFieldEntries.contains(obfFieldEntry) ? m_matchedHighlightPainter : m_unmatchedHighlightPainter
232 );
233 }
234 }
235 }
236
237 protected void onSelectSource(Entry entry) {
238 m_sourceLabel.setText("");
239 m_obfSourceField = null;
240 if (entry != null && entry instanceof FieldEntry) {
241 FieldEntry fieldEntry = (FieldEntry)entry;
242 FieldEntry obfFieldEntry = m_sourceDeobfuscator.obfuscateEntry(fieldEntry);
243 if (m_obfUnmatchedSourceFields.contains(obfFieldEntry)) {
244 m_obfSourceField = obfFieldEntry;
245 m_sourceLabel.setText(fieldEntry.getName() + " " + fieldEntry.getType().toString());
246 }
247 }
248 updateMatchButton();
249 }
127 250
128 m_sourceReader.decompileClass(obfSourceClass, m_sourceDeobfuscator); 251 protected void onSelectDest(Entry entry) {
129 m_destReader.decompileClass(obfDestClass, m_destDeobfuscator); 252 m_destLabel.setText("");
253 m_obfDestField = null;
254 if (entry != null && entry instanceof FieldEntry) {
255 FieldEntry fieldEntry = (FieldEntry)entry;
256 FieldEntry obfFieldEntry = m_destDeobfuscator.obfuscateEntry(fieldEntry);
257 if (m_obfUnmatchedDestFields.contains(obfFieldEntry)) {
258 m_obfDestField = obfFieldEntry;
259 m_destLabel.setText(fieldEntry.getName() + " " + fieldEntry.getType().toString());
260 }
261 }
262 updateMatchButton();
263 }
264
265 private void updateMatchButton() {
266 m_matchButton.setEnabled(m_obfSourceField != null && m_obfDestField != null);
267 }
268
269 protected void match() {
270
271 // update the field matches
272 m_fieldMatches.makeMatch(m_obfSourceField, m_obfDestField);
273 save();
274
275 // update the ui
276 onSelectSource(null);
277 onSelectDest(null);
278 updateUnmatchedFields();
279 updateSourceHighlights();
280 updateDestHighlights();
281 updateSourceClasses();
282 }
283
284 private void save() {
285 if (m_saveListener != null) {
286 m_saveListener.save(m_fieldMatches);
287 }
130 } 288 }
131} 289}