summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/gui/CodeReader.java
diff options
context:
space:
mode:
authorGravatar asiekierka2016-08-17 18:35:12 +0200
committerGravatar asiekierka2016-08-17 18:35:12 +0200
commit5540c815de36e316d0749ce2163f12c61895b327 (patch)
tree2b30d5ae98735ee7cba7d1c0087c51d68ed3ebf9 /src/main/java/cuchaz/enigma/gui/CodeReader.java
parentRevert "Removed util" (diff)
downloadenigma-fork-5540c815de36e316d0749ce2163f12c61895b327.tar.gz
enigma-fork-5540c815de36e316d0749ce2163f12c61895b327.tar.xz
enigma-fork-5540c815de36e316d0749ce2163f12c61895b327.zip
Revert "Removed unused methods"
This reverts commit 1742190f784d0d62e7cc869eebafdfe1927e448f.
Diffstat (limited to 'src/main/java/cuchaz/enigma/gui/CodeReader.java')
-rw-r--r--src/main/java/cuchaz/enigma/gui/CodeReader.java223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/main/java/cuchaz/enigma/gui/CodeReader.java b/src/main/java/cuchaz/enigma/gui/CodeReader.java
new file mode 100644
index 0000000..601e5b9
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/gui/CodeReader.java
@@ -0,0 +1,223 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.gui;
12
13import com.strobel.decompiler.languages.java.ast.CompilationUnit;
14
15import java.awt.Rectangle;
16import java.awt.event.ActionEvent;
17import java.awt.event.ActionListener;
18
19import javax.swing.JEditorPane;
20import javax.swing.SwingUtilities;
21import javax.swing.Timer;
22import javax.swing.event.CaretEvent;
23import javax.swing.event.CaretListener;
24import javax.swing.text.BadLocationException;
25import javax.swing.text.Highlighter.HighlightPainter;
26
27import cuchaz.enigma.Deobfuscator;
28import cuchaz.enigma.analysis.EntryReference;
29import cuchaz.enigma.analysis.SourceIndex;
30import cuchaz.enigma.analysis.Token;
31import cuchaz.enigma.gui.highlight.SelectionHighlightPainter;
32import cuchaz.enigma.mapping.ClassEntry;
33import cuchaz.enigma.mapping.Entry;
34import de.sciss.syntaxpane.DefaultSyntaxKit;
35
36
37public class CodeReader extends JEditorPane {
38
39 private static final long serialVersionUID = 3673180950485748810L;
40
41 private static final Object m_lock = new Object();
42
43 public interface SelectionListener {
44 void onSelect(EntryReference<Entry, Entry> reference);
45 }
46
47 private SelectionHighlightPainter m_selectionHighlightPainter;
48 private SourceIndex m_sourceIndex;
49 private SelectionListener m_selectionListener;
50
51 public CodeReader() {
52
53 setEditable(false);
54 setContentType("text/java");
55
56 // turn off token highlighting (it's wrong most of the time anyway...)
57 DefaultSyntaxKit kit = (DefaultSyntaxKit) getEditorKit();
58 kit.toggleComponent(this, "de.sciss.syntaxpane.components.TokenMarker");
59
60 // hook events
61 addCaretListener(new CaretListener() {
62 @Override
63 public void caretUpdate(CaretEvent event) {
64 if (m_selectionListener != null && m_sourceIndex != null) {
65 Token token = m_sourceIndex.getReferenceToken(event.getDot());
66 if (token != null) {
67 m_selectionListener.onSelect(m_sourceIndex.getDeobfReference(token));
68 } else {
69 m_selectionListener.onSelect(null);
70 }
71 }
72 }
73 });
74
75 m_selectionHighlightPainter = new SelectionHighlightPainter();
76 m_sourceIndex = null;
77 m_selectionListener = null;
78 }
79
80 public void setSelectionListener(SelectionListener val) {
81 m_selectionListener = val;
82 }
83
84 public void setCode(String code) {
85 // sadly, the java lexer is not thread safe, so we have to serialize all these calls
86 synchronized (m_lock) {
87 setText(code);
88 }
89 }
90
91 public SourceIndex getSourceIndex() {
92 return m_sourceIndex;
93 }
94
95 public void decompileClass(ClassEntry classEntry, Deobfuscator deobfuscator) {
96 decompileClass(classEntry, deobfuscator, null);
97 }
98
99 public void decompileClass(ClassEntry classEntry, Deobfuscator deobfuscator, Runnable callback) {
100 decompileClass(classEntry, deobfuscator, null, callback);
101 }
102
103 public void decompileClass(final ClassEntry classEntry, final Deobfuscator deobfuscator, final Boolean ignoreBadTokens, final Runnable callback) {
104
105 if (classEntry == null) {
106 setCode(null);
107 return;
108 }
109
110 setCode("(decompiling...)");
111
112 // run decompilation in a separate thread to keep ui responsive
113 new Thread() {
114 @Override
115 public void run() {
116
117 // decompile it
118 CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getOutermostClassName());
119 String source = deobfuscator.getSource(sourceTree);
120 setCode(source);
121 m_sourceIndex = deobfuscator.getSourceIndex(sourceTree, source, ignoreBadTokens);
122
123 if (callback != null) {
124 callback.run();
125 }
126 }
127 }.start();
128 }
129
130 public void navigateToClassDeclaration(ClassEntry classEntry) {
131
132 // navigate to the class declaration
133 Token token = m_sourceIndex.getDeclarationToken(classEntry);
134 if (token == null) {
135 // couldn't find the class declaration token, might be an anonymous class
136 // look for any declaration in that class instead
137 for (Entry entry : m_sourceIndex.declarations()) {
138 if (entry.getClassEntry().equals(classEntry)) {
139 token = m_sourceIndex.getDeclarationToken(entry);
140 break;
141 }
142 }
143 }
144
145 if (token != null) {
146 navigateToToken(token);
147 } else {
148 // couldn't find anything =(
149 System.out.println("Unable to find declaration in source for " + classEntry);
150 }
151 }
152
153 public void navigateToToken(final Token token) {
154 navigateToToken(this, token, m_selectionHighlightPainter);
155 }
156
157 // HACKHACK: someday we can update the main GUI to use this code reader
158 public static void navigateToToken(final JEditorPane editor, final Token token, final HighlightPainter highlightPainter) {
159
160 // set the caret position to the token
161 editor.setCaretPosition(token.start);
162 editor.grabFocus();
163
164 try {
165 // make sure the token is visible in the scroll window
166 Rectangle start = editor.modelToView(token.start);
167 Rectangle end = editor.modelToView(token.end);
168 final Rectangle show = start.union(end);
169 show.grow(start.width * 10, start.height * 6);
170 SwingUtilities.invokeLater(new Runnable() {
171 @Override
172 public void run() {
173 editor.scrollRectToVisible(show);
174 }
175 });
176 } catch (BadLocationException ex) {
177 throw new Error(ex);
178 }
179
180 // highlight the token momentarily
181 final Timer timer = new Timer(200, new ActionListener() {
182 private int m_counter = 0;
183 private Object m_highlight = null;
184
185 @Override
186 public void actionPerformed(ActionEvent event) {
187 if (m_counter % 2 == 0) {
188 try {
189 m_highlight = editor.getHighlighter().addHighlight(token.start, token.end, highlightPainter);
190 } catch (BadLocationException ex) {
191 // don't care
192 }
193 } else if (m_highlight != null) {
194 editor.getHighlighter().removeHighlight(m_highlight);
195 }
196
197 if (m_counter++ > 6) {
198 Timer timer = (Timer) event.getSource();
199 timer.stop();
200 }
201 }
202 });
203 timer.start();
204 }
205
206 public void setHighlightedTokens(Iterable<Token> tokens, HighlightPainter painter) {
207 for (Token token : tokens) {
208 setHighlightedToken(token, painter);
209 }
210 }
211
212 public void setHighlightedToken(Token token, HighlightPainter painter) {
213 try {
214 getHighlighter().addHighlight(token.start, token.end, painter);
215 } catch (BadLocationException ex) {
216 throw new IllegalArgumentException(ex);
217 }
218 }
219
220 public void clearHighlights() {
221 getHighlighter().removeAllHighlights();
222 }
223}