diff options
| author | 2016-06-30 00:49:21 +1000 | |
|---|---|---|
| committer | 2016-06-30 00:49:21 +1000 | |
| commit | 4be005617b3b8c3578cca07c5d085d12916f0d1d (patch) | |
| tree | db163431f38703e26da417ef05eaea2b27a498b9 /src/cuchaz/enigma/gui/Gui.java | |
| parent | Some small changes to fix idea importing (diff) | |
| download | enigma-fork-4be005617b3b8c3578cca07c5d085d12916f0d1d.tar.gz enigma-fork-4be005617b3b8c3578cca07c5d085d12916f0d1d.tar.xz enigma-fork-4be005617b3b8c3578cca07c5d085d12916f0d1d.zip | |
Json format (#2)
* Added new format
* Fixed bug
* Updated Version
Diffstat (limited to 'src/cuchaz/enigma/gui/Gui.java')
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 1122 |
1 files changed, 0 insertions, 1122 deletions
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java deleted file mode 100644 index f9192d3..0000000 --- a/src/cuchaz/enigma/gui/Gui.java +++ /dev/null | |||
| @@ -1,1122 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.gui; | ||
| 12 | |||
| 13 | import java.awt.BorderLayout; | ||
| 14 | import java.awt.Color; | ||
| 15 | import java.awt.Container; | ||
| 16 | import java.awt.Dimension; | ||
| 17 | import java.awt.FlowLayout; | ||
| 18 | import java.awt.GridLayout; | ||
| 19 | import java.awt.event.ActionEvent; | ||
| 20 | import java.awt.event.ActionListener; | ||
| 21 | import java.awt.event.InputEvent; | ||
| 22 | import java.awt.event.KeyAdapter; | ||
| 23 | import java.awt.event.KeyEvent; | ||
| 24 | import java.awt.event.MouseAdapter; | ||
| 25 | import java.awt.event.MouseEvent; | ||
| 26 | import java.awt.event.WindowAdapter; | ||
| 27 | import java.awt.event.WindowEvent; | ||
| 28 | import java.io.File; | ||
| 29 | import java.io.IOException; | ||
| 30 | import java.lang.Thread.UncaughtExceptionHandler; | ||
| 31 | import java.util.Collection; | ||
| 32 | import java.util.Collections; | ||
| 33 | import java.util.List; | ||
| 34 | import java.util.Vector; | ||
| 35 | import java.util.jar.JarFile; | ||
| 36 | |||
| 37 | import javax.swing.BorderFactory; | ||
| 38 | import javax.swing.JEditorPane; | ||
| 39 | import javax.swing.JFileChooser; | ||
| 40 | import javax.swing.JFrame; | ||
| 41 | import javax.swing.JLabel; | ||
| 42 | import javax.swing.JList; | ||
| 43 | import javax.swing.JMenu; | ||
| 44 | import javax.swing.JMenuBar; | ||
| 45 | import javax.swing.JMenuItem; | ||
| 46 | import javax.swing.JOptionPane; | ||
| 47 | import javax.swing.JPanel; | ||
| 48 | import javax.swing.JPopupMenu; | ||
| 49 | import javax.swing.JScrollPane; | ||
| 50 | import javax.swing.JSplitPane; | ||
| 51 | import javax.swing.JTabbedPane; | ||
| 52 | import javax.swing.JTextField; | ||
| 53 | import javax.swing.JTree; | ||
| 54 | import javax.swing.KeyStroke; | ||
| 55 | import javax.swing.ListSelectionModel; | ||
| 56 | import javax.swing.WindowConstants; | ||
| 57 | import javax.swing.event.CaretEvent; | ||
| 58 | import javax.swing.event.CaretListener; | ||
| 59 | import javax.swing.text.BadLocationException; | ||
| 60 | import javax.swing.text.Highlighter; | ||
| 61 | import javax.swing.tree.DefaultTreeModel; | ||
| 62 | import javax.swing.tree.TreeNode; | ||
| 63 | import javax.swing.tree.TreePath; | ||
| 64 | |||
| 65 | import com.google.common.collect.Lists; | ||
| 66 | |||
| 67 | import cuchaz.enigma.Constants; | ||
| 68 | import cuchaz.enigma.ExceptionIgnorer; | ||
| 69 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; | ||
| 70 | import cuchaz.enigma.analysis.ClassImplementationsTreeNode; | ||
| 71 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; | ||
| 72 | import cuchaz.enigma.analysis.EntryReference; | ||
| 73 | import cuchaz.enigma.analysis.FieldReferenceTreeNode; | ||
| 74 | import cuchaz.enigma.analysis.MethodImplementationsTreeNode; | ||
| 75 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | ||
| 76 | import cuchaz.enigma.analysis.ReferenceTreeNode; | ||
| 77 | import cuchaz.enigma.analysis.Token; | ||
| 78 | import cuchaz.enigma.gui.ClassSelector.ClassSelectionListener; | ||
| 79 | import cuchaz.enigma.mapping.ArgumentEntry; | ||
| 80 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 81 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 82 | import cuchaz.enigma.mapping.Entry; | ||
| 83 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 84 | import cuchaz.enigma.mapping.IllegalNameException; | ||
| 85 | import cuchaz.enigma.mapping.MappingParseException; | ||
| 86 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 87 | import cuchaz.enigma.mapping.Signature; | ||
| 88 | import de.sciss.syntaxpane.DefaultSyntaxKit; | ||
| 89 | |||
| 90 | public class Gui { | ||
| 91 | |||
| 92 | private GuiController m_controller; | ||
| 93 | |||
| 94 | // controls | ||
| 95 | private JFrame m_frame; | ||
| 96 | private ClassSelector m_obfClasses; | ||
| 97 | private ClassSelector m_deobfClasses; | ||
| 98 | private JEditorPane m_editor; | ||
| 99 | private JPanel m_classesPanel; | ||
| 100 | private JSplitPane m_splitClasses; | ||
| 101 | private JPanel m_infoPanel; | ||
| 102 | private ObfuscatedHighlightPainter m_obfuscatedHighlightPainter; | ||
| 103 | private DeobfuscatedHighlightPainter m_deobfuscatedHighlightPainter; | ||
| 104 | private OtherHighlightPainter m_otherHighlightPainter; | ||
| 105 | private SelectionHighlightPainter m_selectionHighlightPainter; | ||
| 106 | private JTree m_inheritanceTree; | ||
| 107 | private JTree m_implementationsTree; | ||
| 108 | private JTree m_callsTree; | ||
| 109 | private JList<Token> m_tokens; | ||
| 110 | private JTabbedPane m_tabs; | ||
| 111 | |||
| 112 | // dynamic menu items | ||
| 113 | private JMenuItem m_closeJarMenu; | ||
| 114 | private JMenuItem m_openMappingsMenu; | ||
| 115 | private JMenuItem m_saveMappingsMenu; | ||
| 116 | private JMenuItem m_saveMappingsAsMenu; | ||
| 117 | private JMenuItem m_closeMappingsMenu; | ||
| 118 | private JMenuItem m_renameMenu; | ||
| 119 | private JMenuItem m_showInheritanceMenu; | ||
| 120 | private JMenuItem m_openEntryMenu; | ||
| 121 | private JMenuItem m_openPreviousMenu; | ||
| 122 | private JMenuItem m_showCallsMenu; | ||
| 123 | private JMenuItem m_showImplementationsMenu; | ||
| 124 | private JMenuItem m_toggleMappingMenu; | ||
| 125 | private JMenuItem m_exportSourceMenu; | ||
| 126 | private JMenuItem m_exportJarMenu; | ||
| 127 | |||
| 128 | // state | ||
| 129 | private EntryReference<Entry,Entry> m_reference; | ||
| 130 | private JFileChooser m_jarFileChooser; | ||
| 131 | private JFileChooser m_mappingsFileChooser; | ||
| 132 | private JFileChooser m_exportSourceFileChooser; | ||
| 133 | private JFileChooser m_exportJarFileChooser; | ||
| 134 | |||
| 135 | public Gui() { | ||
| 136 | |||
| 137 | // init frame | ||
| 138 | m_frame = new JFrame(Constants.Name); | ||
| 139 | final Container pane = m_frame.getContentPane(); | ||
| 140 | pane.setLayout(new BorderLayout()); | ||
| 141 | |||
| 142 | if (Boolean.parseBoolean(System.getProperty("enigma.catchExceptions", "true"))) { | ||
| 143 | // install a global exception handler to the event thread | ||
| 144 | CrashDialog.init(m_frame); | ||
| 145 | Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { | ||
| 146 | @Override | ||
| 147 | public void uncaughtException(Thread thread, Throwable t) { | ||
| 148 | t.printStackTrace(System.err); | ||
| 149 | if (!ExceptionIgnorer.shouldIgnore(t)) { | ||
| 150 | CrashDialog.show(t); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | }); | ||
| 154 | } | ||
| 155 | |||
| 156 | m_controller = new GuiController(this); | ||
| 157 | |||
| 158 | // init file choosers | ||
| 159 | m_jarFileChooser = new JFileChooser(); | ||
| 160 | m_mappingsFileChooser = new JFileChooser(); | ||
| 161 | m_exportSourceFileChooser = new JFileChooser(); | ||
| 162 | m_exportSourceFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); | ||
| 163 | m_exportJarFileChooser = new JFileChooser(); | ||
| 164 | |||
| 165 | // init obfuscated classes list | ||
| 166 | m_obfClasses = new ClassSelector(ClassSelector.ObfuscatedClassEntryComparator); | ||
| 167 | m_obfClasses.setListener(new ClassSelectionListener() { | ||
| 168 | @Override | ||
| 169 | public void onSelectClass(ClassEntry classEntry) { | ||
| 170 | navigateTo(classEntry); | ||
| 171 | } | ||
| 172 | }); | ||
| 173 | JScrollPane obfScroller = new JScrollPane(m_obfClasses); | ||
| 174 | JPanel obfPanel = new JPanel(); | ||
| 175 | obfPanel.setLayout(new BorderLayout()); | ||
| 176 | obfPanel.add(new JLabel("Obfuscated Classes"), BorderLayout.NORTH); | ||
| 177 | obfPanel.add(obfScroller, BorderLayout.CENTER); | ||
| 178 | |||
| 179 | // init deobfuscated classes list | ||
| 180 | m_deobfClasses = new ClassSelector(ClassSelector.DeobfuscatedClassEntryComparator); | ||
| 181 | m_deobfClasses.setListener(new ClassSelectionListener() { | ||
| 182 | @Override | ||
| 183 | public void onSelectClass(ClassEntry classEntry) { | ||
| 184 | navigateTo(classEntry); | ||
| 185 | } | ||
| 186 | }); | ||
| 187 | JScrollPane deobfScroller = new JScrollPane(m_deobfClasses); | ||
| 188 | JPanel deobfPanel = new JPanel(); | ||
| 189 | deobfPanel.setLayout(new BorderLayout()); | ||
| 190 | deobfPanel.add(new JLabel("De-obfuscated Classes"), BorderLayout.NORTH); | ||
| 191 | deobfPanel.add(deobfScroller, BorderLayout.CENTER); | ||
| 192 | |||
| 193 | // set up classes panel (don't add the splitter yet) | ||
| 194 | m_splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel); | ||
| 195 | m_splitClasses.setResizeWeight(0.3); | ||
| 196 | m_classesPanel = new JPanel(); | ||
| 197 | m_classesPanel.setLayout(new BorderLayout()); | ||
| 198 | m_classesPanel.setPreferredSize(new Dimension(250, 0)); | ||
| 199 | |||
| 200 | // init info panel | ||
| 201 | m_infoPanel = new JPanel(); | ||
| 202 | m_infoPanel.setLayout(new GridLayout(4, 1, 0, 0)); | ||
| 203 | m_infoPanel.setPreferredSize(new Dimension(0, 100)); | ||
| 204 | m_infoPanel.setBorder(BorderFactory.createTitledBorder("Identifier Info")); | ||
| 205 | clearReference(); | ||
| 206 | |||
| 207 | // init editor | ||
| 208 | DefaultSyntaxKit.initKit(); | ||
| 209 | m_obfuscatedHighlightPainter = new ObfuscatedHighlightPainter(); | ||
| 210 | m_deobfuscatedHighlightPainter = new DeobfuscatedHighlightPainter(); | ||
| 211 | m_otherHighlightPainter = new OtherHighlightPainter(); | ||
| 212 | m_selectionHighlightPainter = new SelectionHighlightPainter(); | ||
| 213 | m_editor = new JEditorPane(); | ||
| 214 | m_editor.setEditable(false); | ||
| 215 | m_editor.setCaret(new BrowserCaret()); | ||
| 216 | JScrollPane sourceScroller = new JScrollPane(m_editor); | ||
| 217 | m_editor.setContentType("text/java"); | ||
| 218 | m_editor.addCaretListener(new CaretListener() { | ||
| 219 | @Override | ||
| 220 | public void caretUpdate(CaretEvent event) { | ||
| 221 | onCaretMove(event.getDot()); | ||
| 222 | } | ||
| 223 | }); | ||
| 224 | m_editor.addKeyListener(new KeyAdapter() { | ||
| 225 | @Override | ||
| 226 | public void keyPressed(KeyEvent event) { | ||
| 227 | switch (event.getKeyCode()) { | ||
| 228 | case KeyEvent.VK_R: | ||
| 229 | m_renameMenu.doClick(); | ||
| 230 | break; | ||
| 231 | |||
| 232 | case KeyEvent.VK_I: | ||
| 233 | m_showInheritanceMenu.doClick(); | ||
| 234 | break; | ||
| 235 | |||
| 236 | case KeyEvent.VK_M: | ||
| 237 | m_showImplementationsMenu.doClick(); | ||
| 238 | break; | ||
| 239 | |||
| 240 | case KeyEvent.VK_N: | ||
| 241 | m_openEntryMenu.doClick(); | ||
| 242 | break; | ||
| 243 | |||
| 244 | case KeyEvent.VK_P: | ||
| 245 | m_openPreviousMenu.doClick(); | ||
| 246 | break; | ||
| 247 | |||
| 248 | case KeyEvent.VK_C: | ||
| 249 | m_showCallsMenu.doClick(); | ||
| 250 | break; | ||
| 251 | |||
| 252 | case KeyEvent.VK_T: | ||
| 253 | m_toggleMappingMenu.doClick(); | ||
| 254 | break; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | }); | ||
| 258 | |||
| 259 | // turn off token highlighting (it's wrong most of the time anyway...) | ||
| 260 | DefaultSyntaxKit kit = (DefaultSyntaxKit)m_editor.getEditorKit(); | ||
| 261 | kit.toggleComponent(m_editor, "de.sciss.syntaxpane.components.TokenMarker"); | ||
| 262 | |||
| 263 | // init editor popup menu | ||
| 264 | JPopupMenu popupMenu = new JPopupMenu(); | ||
| 265 | m_editor.setComponentPopupMenu(popupMenu); | ||
| 266 | { | ||
| 267 | JMenuItem menu = new JMenuItem("Rename"); | ||
| 268 | menu.addActionListener(new ActionListener() { | ||
| 269 | @Override | ||
| 270 | public void actionPerformed(ActionEvent event) { | ||
| 271 | startRename(); | ||
| 272 | } | ||
| 273 | }); | ||
| 274 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0)); | ||
| 275 | menu.setEnabled(false); | ||
| 276 | popupMenu.add(menu); | ||
| 277 | m_renameMenu = menu; | ||
| 278 | } | ||
| 279 | { | ||
| 280 | JMenuItem menu = new JMenuItem("Show Inheritance"); | ||
| 281 | menu.addActionListener(new ActionListener() { | ||
| 282 | @Override | ||
| 283 | public void actionPerformed(ActionEvent event) { | ||
| 284 | showInheritance(); | ||
| 285 | } | ||
| 286 | }); | ||
| 287 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 0)); | ||
| 288 | menu.setEnabled(false); | ||
| 289 | popupMenu.add(menu); | ||
| 290 | m_showInheritanceMenu = menu; | ||
| 291 | } | ||
| 292 | { | ||
| 293 | JMenuItem menu = new JMenuItem("Show Implementations"); | ||
| 294 | menu.addActionListener(new ActionListener() { | ||
| 295 | @Override | ||
| 296 | public void actionPerformed(ActionEvent event) { | ||
| 297 | showImplementations(); | ||
| 298 | } | ||
| 299 | }); | ||
| 300 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, 0)); | ||
| 301 | menu.setEnabled(false); | ||
| 302 | popupMenu.add(menu); | ||
| 303 | m_showImplementationsMenu = menu; | ||
| 304 | } | ||
| 305 | { | ||
| 306 | JMenuItem menu = new JMenuItem("Show Calls"); | ||
| 307 | menu.addActionListener(new ActionListener() { | ||
| 308 | @Override | ||
| 309 | public void actionPerformed(ActionEvent event) { | ||
| 310 | showCalls(); | ||
| 311 | } | ||
| 312 | }); | ||
| 313 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 0)); | ||
| 314 | menu.setEnabled(false); | ||
| 315 | popupMenu.add(menu); | ||
| 316 | m_showCallsMenu = menu; | ||
| 317 | } | ||
| 318 | { | ||
| 319 | JMenuItem menu = new JMenuItem("Go to Declaration"); | ||
| 320 | menu.addActionListener(new ActionListener() { | ||
| 321 | @Override | ||
| 322 | public void actionPerformed(ActionEvent event) { | ||
| 323 | navigateTo(m_reference.entry); | ||
| 324 | } | ||
| 325 | }); | ||
| 326 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0)); | ||
| 327 | menu.setEnabled(false); | ||
| 328 | popupMenu.add(menu); | ||
| 329 | m_openEntryMenu = menu; | ||
| 330 | } | ||
| 331 | { | ||
| 332 | JMenuItem menu = new JMenuItem("Go to previous"); | ||
| 333 | menu.addActionListener(new ActionListener() { | ||
| 334 | @Override | ||
| 335 | public void actionPerformed(ActionEvent event) { | ||
| 336 | m_controller.openPreviousReference(); | ||
| 337 | } | ||
| 338 | }); | ||
| 339 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0)); | ||
| 340 | menu.setEnabled(false); | ||
| 341 | popupMenu.add(menu); | ||
| 342 | m_openPreviousMenu = menu; | ||
| 343 | } | ||
| 344 | { | ||
| 345 | JMenuItem menu = new JMenuItem("Mark as deobfuscated"); | ||
| 346 | menu.addActionListener(new ActionListener() { | ||
| 347 | @Override | ||
| 348 | public void actionPerformed(ActionEvent event) { | ||
| 349 | toggleMapping(); | ||
| 350 | } | ||
| 351 | }); | ||
| 352 | menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0)); | ||
| 353 | menu.setEnabled(false); | ||
| 354 | popupMenu.add(menu); | ||
| 355 | m_toggleMappingMenu = menu; | ||
| 356 | } | ||
| 357 | |||
| 358 | // init inheritance panel | ||
| 359 | m_inheritanceTree = new JTree(); | ||
| 360 | m_inheritanceTree.setModel(null); | ||
| 361 | m_inheritanceTree.addMouseListener(new MouseAdapter() { | ||
| 362 | @Override | ||
| 363 | public void mouseClicked(MouseEvent event) { | ||
| 364 | if (event.getClickCount() == 2) { | ||
| 365 | // get the selected node | ||
| 366 | TreePath path = m_inheritanceTree.getSelectionPath(); | ||
| 367 | if (path == null) { | ||
| 368 | return; | ||
| 369 | } | ||
| 370 | |||
| 371 | Object node = path.getLastPathComponent(); | ||
| 372 | if (node instanceof ClassInheritanceTreeNode) { | ||
| 373 | ClassInheritanceTreeNode classNode = (ClassInheritanceTreeNode)node; | ||
| 374 | navigateTo(new ClassEntry(classNode.getObfClassName())); | ||
| 375 | } else if (node instanceof MethodInheritanceTreeNode) { | ||
| 376 | MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode)node; | ||
| 377 | if (methodNode.isImplemented()) { | ||
| 378 | navigateTo(methodNode.getMethodEntry()); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | } | ||
| 383 | }); | ||
| 384 | JPanel inheritancePanel = new JPanel(); | ||
| 385 | inheritancePanel.setLayout(new BorderLayout()); | ||
| 386 | inheritancePanel.add(new JScrollPane(m_inheritanceTree)); | ||
| 387 | |||
| 388 | // init implementations panel | ||
| 389 | m_implementationsTree = new JTree(); | ||
| 390 | m_implementationsTree.setModel(null); | ||
| 391 | m_implementationsTree.addMouseListener(new MouseAdapter() { | ||
| 392 | @Override | ||
| 393 | public void mouseClicked(MouseEvent event) { | ||
| 394 | if (event.getClickCount() == 2) { | ||
| 395 | // get the selected node | ||
| 396 | TreePath path = m_implementationsTree.getSelectionPath(); | ||
| 397 | if (path == null) { | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | |||
| 401 | Object node = path.getLastPathComponent(); | ||
| 402 | if (node instanceof ClassImplementationsTreeNode) { | ||
| 403 | ClassImplementationsTreeNode classNode = (ClassImplementationsTreeNode)node; | ||
| 404 | navigateTo(classNode.getClassEntry()); | ||
| 405 | } else if (node instanceof MethodImplementationsTreeNode) { | ||
| 406 | MethodImplementationsTreeNode methodNode = (MethodImplementationsTreeNode)node; | ||
| 407 | navigateTo(methodNode.getMethodEntry()); | ||
| 408 | } | ||
| 409 | } | ||
| 410 | } | ||
| 411 | }); | ||
| 412 | JPanel implementationsPanel = new JPanel(); | ||
| 413 | implementationsPanel.setLayout(new BorderLayout()); | ||
| 414 | implementationsPanel.add(new JScrollPane(m_implementationsTree)); | ||
| 415 | |||
| 416 | // init call panel | ||
| 417 | m_callsTree = new JTree(); | ||
| 418 | m_callsTree.setModel(null); | ||
| 419 | m_callsTree.addMouseListener(new MouseAdapter() { | ||
| 420 | @SuppressWarnings("unchecked") | ||
| 421 | @Override | ||
| 422 | public void mouseClicked(MouseEvent event) { | ||
| 423 | if (event.getClickCount() == 2) { | ||
| 424 | // get the selected node | ||
| 425 | TreePath path = m_callsTree.getSelectionPath(); | ||
| 426 | if (path == null) { | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | |||
| 430 | Object node = path.getLastPathComponent(); | ||
| 431 | if (node instanceof ReferenceTreeNode) { | ||
| 432 | ReferenceTreeNode<Entry,Entry> referenceNode = ((ReferenceTreeNode<Entry,Entry>)node); | ||
| 433 | if (referenceNode.getReference() != null) { | ||
| 434 | navigateTo(referenceNode.getReference()); | ||
| 435 | } else { | ||
| 436 | navigateTo(referenceNode.getEntry()); | ||
| 437 | } | ||
| 438 | } | ||
| 439 | } | ||
| 440 | } | ||
| 441 | }); | ||
| 442 | m_tokens = new JList<Token>(); | ||
| 443 | m_tokens.setCellRenderer(new TokenListCellRenderer(m_controller)); | ||
| 444 | m_tokens.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | ||
| 445 | m_tokens.setLayoutOrientation(JList.VERTICAL); | ||
| 446 | m_tokens.addMouseListener(new MouseAdapter() { | ||
| 447 | @Override | ||
| 448 | public void mouseClicked(MouseEvent event) { | ||
| 449 | if (event.getClickCount() == 2) { | ||
| 450 | Token selected = m_tokens.getSelectedValue(); | ||
| 451 | if (selected != null) { | ||
| 452 | showToken(selected); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | } | ||
| 456 | }); | ||
| 457 | m_tokens.setPreferredSize(new Dimension(0, 200)); | ||
| 458 | m_tokens.setMinimumSize(new Dimension(0, 200)); | ||
| 459 | JSplitPane callPanel = new JSplitPane( | ||
| 460 | JSplitPane.VERTICAL_SPLIT, | ||
| 461 | true, | ||
| 462 | new JScrollPane(m_callsTree), | ||
| 463 | new JScrollPane(m_tokens) | ||
| 464 | ); | ||
| 465 | callPanel.setResizeWeight(1); // let the top side take all the slack | ||
| 466 | callPanel.resetToPreferredSizes(); | ||
| 467 | |||
| 468 | // layout controls | ||
| 469 | JPanel centerPanel = new JPanel(); | ||
| 470 | centerPanel.setLayout(new BorderLayout()); | ||
| 471 | centerPanel.add(m_infoPanel, BorderLayout.NORTH); | ||
| 472 | centerPanel.add(sourceScroller, BorderLayout.CENTER); | ||
| 473 | m_tabs = new JTabbedPane(); | ||
| 474 | m_tabs.setPreferredSize(new Dimension(250, 0)); | ||
| 475 | m_tabs.addTab("Inheritance", inheritancePanel); | ||
| 476 | m_tabs.addTab("Implementations", implementationsPanel); | ||
| 477 | m_tabs.addTab("Call Graph", callPanel); | ||
| 478 | JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs); | ||
| 479 | splitRight.setResizeWeight(1); // let the left side take all the slack | ||
| 480 | splitRight.resetToPreferredSizes(); | ||
| 481 | JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, m_classesPanel, splitRight); | ||
| 482 | splitCenter.setResizeWeight(0); // let the right side take all the slack | ||
| 483 | pane.add(splitCenter, BorderLayout.CENTER); | ||
| 484 | |||
| 485 | // init menus | ||
| 486 | JMenuBar menuBar = new JMenuBar(); | ||
| 487 | m_frame.setJMenuBar(menuBar); | ||
| 488 | { | ||
| 489 | JMenu menu = new JMenu("File"); | ||
| 490 | menuBar.add(menu); | ||
| 491 | { | ||
| 492 | JMenuItem item = new JMenuItem("Open Jar..."); | ||
| 493 | menu.add(item); | ||
| 494 | item.addActionListener(new ActionListener() { | ||
| 495 | @Override | ||
| 496 | public void actionPerformed(ActionEvent event) { | ||
| 497 | if (m_jarFileChooser.showOpenDialog(m_frame) == JFileChooser.APPROVE_OPTION) { | ||
| 498 | // load the jar in a separate thread | ||
| 499 | new Thread() { | ||
| 500 | @Override | ||
| 501 | public void run() { | ||
| 502 | try { | ||
| 503 | m_controller.openJar(new JarFile(m_jarFileChooser.getSelectedFile())); | ||
| 504 | } catch (IOException ex) { | ||
| 505 | throw new Error(ex); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | }.start(); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | }); | ||
| 512 | } | ||
| 513 | { | ||
| 514 | JMenuItem item = new JMenuItem("Close Jar"); | ||
| 515 | menu.add(item); | ||
| 516 | item.addActionListener(new ActionListener() { | ||
| 517 | @Override | ||
| 518 | public void actionPerformed(ActionEvent event) { | ||
| 519 | m_controller.closeJar(); | ||
| 520 | } | ||
| 521 | }); | ||
| 522 | m_closeJarMenu = item; | ||
| 523 | } | ||
| 524 | menu.addSeparator(); | ||
| 525 | { | ||
| 526 | JMenuItem item = new JMenuItem("Open Mappings..."); | ||
| 527 | menu.add(item); | ||
| 528 | item.addActionListener(new ActionListener() { | ||
| 529 | @Override | ||
| 530 | public void actionPerformed(ActionEvent event) { | ||
| 531 | if (m_mappingsFileChooser.showOpenDialog(m_frame) == JFileChooser.APPROVE_OPTION) { | ||
| 532 | try { | ||
| 533 | m_controller.openMappings(m_mappingsFileChooser.getSelectedFile()); | ||
| 534 | } catch (IOException ex) { | ||
| 535 | throw new Error(ex); | ||
| 536 | } catch (MappingParseException ex) { | ||
| 537 | JOptionPane.showMessageDialog(m_frame, ex.getMessage()); | ||
| 538 | } | ||
| 539 | } | ||
| 540 | } | ||
| 541 | }); | ||
| 542 | m_openMappingsMenu = item; | ||
| 543 | } | ||
| 544 | { | ||
| 545 | JMenuItem item = new JMenuItem("Save Mappings"); | ||
| 546 | menu.add(item); | ||
| 547 | item.addActionListener(new ActionListener() { | ||
| 548 | @Override | ||
| 549 | public void actionPerformed(ActionEvent event) { | ||
| 550 | try { | ||
| 551 | m_controller.saveMappings(m_mappingsFileChooser.getSelectedFile()); | ||
| 552 | } catch (IOException ex) { | ||
| 553 | throw new Error(ex); | ||
| 554 | } | ||
| 555 | } | ||
| 556 | }); | ||
| 557 | item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); | ||
| 558 | m_saveMappingsMenu = item; | ||
| 559 | } | ||
| 560 | { | ||
| 561 | JMenuItem item = new JMenuItem("Save Mappings As..."); | ||
| 562 | menu.add(item); | ||
| 563 | item.addActionListener(new ActionListener() { | ||
| 564 | @Override | ||
| 565 | public void actionPerformed(ActionEvent event) { | ||
| 566 | if (m_mappingsFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { | ||
| 567 | try { | ||
| 568 | m_controller.saveMappings(m_mappingsFileChooser.getSelectedFile()); | ||
| 569 | m_saveMappingsMenu.setEnabled(true); | ||
| 570 | } catch (IOException ex) { | ||
| 571 | throw new Error(ex); | ||
| 572 | } | ||
| 573 | } | ||
| 574 | } | ||
| 575 | }); | ||
| 576 | item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); | ||
| 577 | m_saveMappingsAsMenu = item; | ||
| 578 | } | ||
| 579 | { | ||
| 580 | JMenuItem item = new JMenuItem("Close Mappings"); | ||
| 581 | menu.add(item); | ||
| 582 | item.addActionListener(new ActionListener() { | ||
| 583 | @Override | ||
| 584 | public void actionPerformed(ActionEvent event) { | ||
| 585 | m_controller.closeMappings(); | ||
| 586 | } | ||
| 587 | }); | ||
| 588 | m_closeMappingsMenu = item; | ||
| 589 | } | ||
| 590 | menu.addSeparator(); | ||
| 591 | { | ||
| 592 | JMenuItem item = new JMenuItem("Export Source..."); | ||
| 593 | menu.add(item); | ||
| 594 | item.addActionListener(new ActionListener() { | ||
| 595 | @Override | ||
| 596 | public void actionPerformed(ActionEvent event) { | ||
| 597 | if (m_exportSourceFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { | ||
| 598 | m_controller.exportSource(m_exportSourceFileChooser.getSelectedFile()); | ||
| 599 | } | ||
| 600 | } | ||
| 601 | }); | ||
| 602 | m_exportSourceMenu = item; | ||
| 603 | } | ||
| 604 | { | ||
| 605 | JMenuItem item = new JMenuItem("Export Jar..."); | ||
| 606 | menu.add(item); | ||
| 607 | item.addActionListener(new ActionListener() { | ||
| 608 | @Override | ||
| 609 | public void actionPerformed(ActionEvent event) { | ||
| 610 | if (m_exportJarFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { | ||
| 611 | m_controller.exportJar(m_exportJarFileChooser.getSelectedFile()); | ||
| 612 | } | ||
| 613 | } | ||
| 614 | }); | ||
| 615 | m_exportJarMenu = item; | ||
| 616 | } | ||
| 617 | menu.addSeparator(); | ||
| 618 | { | ||
| 619 | JMenuItem item = new JMenuItem("Exit"); | ||
| 620 | menu.add(item); | ||
| 621 | item.addActionListener(new ActionListener() { | ||
| 622 | @Override | ||
| 623 | public void actionPerformed(ActionEvent event) { | ||
| 624 | close(); | ||
| 625 | } | ||
| 626 | }); | ||
| 627 | } | ||
| 628 | } | ||
| 629 | { | ||
| 630 | JMenu menu = new JMenu("Help"); | ||
| 631 | menuBar.add(menu); | ||
| 632 | { | ||
| 633 | JMenuItem item = new JMenuItem("About"); | ||
| 634 | menu.add(item); | ||
| 635 | item.addActionListener(new ActionListener() { | ||
| 636 | @Override | ||
| 637 | public void actionPerformed(ActionEvent event) { | ||
| 638 | AboutDialog.show(m_frame); | ||
| 639 | } | ||
| 640 | }); | ||
| 641 | } | ||
| 642 | } | ||
| 643 | |||
| 644 | // init state | ||
| 645 | onCloseJar(); | ||
| 646 | |||
| 647 | m_frame.addWindowListener(new WindowAdapter() { | ||
| 648 | @Override | ||
| 649 | public void windowClosing(WindowEvent event) { | ||
| 650 | close(); | ||
| 651 | } | ||
| 652 | }); | ||
| 653 | |||
| 654 | // show the frame | ||
| 655 | pane.doLayout(); | ||
| 656 | m_frame.setSize(1024, 576); | ||
| 657 | m_frame.setMinimumSize(new Dimension(640, 480)); | ||
| 658 | m_frame.setVisible(true); | ||
| 659 | m_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); | ||
| 660 | } | ||
| 661 | |||
| 662 | public JFrame getFrame() { | ||
| 663 | return m_frame; | ||
| 664 | } | ||
| 665 | |||
| 666 | public GuiController getController() { | ||
| 667 | return m_controller; | ||
| 668 | } | ||
| 669 | |||
| 670 | public void onStartOpenJar() { | ||
| 671 | m_classesPanel.removeAll(); | ||
| 672 | JPanel panel = new JPanel(); | ||
| 673 | panel.setLayout(new FlowLayout()); | ||
| 674 | panel.add(new JLabel("Loading...")); | ||
| 675 | m_classesPanel.add(panel); | ||
| 676 | redraw(); | ||
| 677 | } | ||
| 678 | |||
| 679 | public void onFinishOpenJar(String jarName) { | ||
| 680 | // update gui | ||
| 681 | m_frame.setTitle(Constants.Name + " - " + jarName); | ||
| 682 | m_classesPanel.removeAll(); | ||
| 683 | m_classesPanel.add(m_splitClasses); | ||
| 684 | setSource(null); | ||
| 685 | |||
| 686 | // update menu | ||
| 687 | m_closeJarMenu.setEnabled(true); | ||
| 688 | m_openMappingsMenu.setEnabled(true); | ||
| 689 | m_saveMappingsMenu.setEnabled(false); | ||
| 690 | m_saveMappingsAsMenu.setEnabled(true); | ||
| 691 | m_closeMappingsMenu.setEnabled(true); | ||
| 692 | m_exportSourceMenu.setEnabled(true); | ||
| 693 | m_exportJarMenu.setEnabled(true); | ||
| 694 | |||
| 695 | redraw(); | ||
| 696 | } | ||
| 697 | |||
| 698 | public void onCloseJar() { | ||
| 699 | // update gui | ||
| 700 | m_frame.setTitle(Constants.Name); | ||
| 701 | setObfClasses(null); | ||
| 702 | setDeobfClasses(null); | ||
| 703 | setSource(null); | ||
| 704 | m_classesPanel.removeAll(); | ||
| 705 | |||
| 706 | // update menu | ||
| 707 | m_closeJarMenu.setEnabled(false); | ||
| 708 | m_openMappingsMenu.setEnabled(false); | ||
| 709 | m_saveMappingsMenu.setEnabled(false); | ||
| 710 | m_saveMappingsAsMenu.setEnabled(false); | ||
| 711 | m_closeMappingsMenu.setEnabled(false); | ||
| 712 | m_exportSourceMenu.setEnabled(false); | ||
| 713 | m_exportJarMenu.setEnabled(false); | ||
| 714 | |||
| 715 | redraw(); | ||
| 716 | } | ||
| 717 | |||
| 718 | public void setObfClasses(Collection<ClassEntry> obfClasses) { | ||
| 719 | m_obfClasses.setClasses(obfClasses); | ||
| 720 | } | ||
| 721 | |||
| 722 | public void setDeobfClasses(Collection<ClassEntry> deobfClasses) { | ||
| 723 | m_deobfClasses.setClasses(deobfClasses); | ||
| 724 | } | ||
| 725 | |||
| 726 | public void setMappingsFile(File file) { | ||
| 727 | m_mappingsFileChooser.setSelectedFile(file); | ||
| 728 | m_saveMappingsMenu.setEnabled(file != null); | ||
| 729 | } | ||
| 730 | |||
| 731 | public void setSource(String source) { | ||
| 732 | m_editor.getHighlighter().removeAllHighlights(); | ||
| 733 | m_editor.setText(source); | ||
| 734 | } | ||
| 735 | |||
| 736 | public void showToken(final Token token) { | ||
| 737 | if (token == null) { | ||
| 738 | throw new IllegalArgumentException("Token cannot be null!"); | ||
| 739 | } | ||
| 740 | CodeReader.navigateToToken(m_editor, token, m_selectionHighlightPainter); | ||
| 741 | redraw(); | ||
| 742 | } | ||
| 743 | |||
| 744 | public void showTokens(Collection<Token> tokens) { | ||
| 745 | Vector<Token> sortedTokens = new Vector<Token>(tokens); | ||
| 746 | Collections.sort(sortedTokens); | ||
| 747 | if (sortedTokens.size() > 1) { | ||
| 748 | // sort the tokens and update the tokens panel | ||
| 749 | m_tokens.setListData(sortedTokens); | ||
| 750 | m_tokens.setSelectedIndex(0); | ||
| 751 | } else { | ||
| 752 | m_tokens.setListData(new Vector<Token>()); | ||
| 753 | } | ||
| 754 | |||
| 755 | // show the first token | ||
| 756 | showToken(sortedTokens.get(0)); | ||
| 757 | } | ||
| 758 | |||
| 759 | public void setHighlightedTokens(Iterable<Token> obfuscatedTokens, Iterable<Token> deobfuscatedTokens, Iterable<Token> otherTokens) { | ||
| 760 | |||
| 761 | // remove any old highlighters | ||
| 762 | m_editor.getHighlighter().removeAllHighlights(); | ||
| 763 | |||
| 764 | // color things based on the index | ||
| 765 | if (obfuscatedTokens != null) { | ||
| 766 | setHighlightedTokens(obfuscatedTokens, m_obfuscatedHighlightPainter); | ||
| 767 | } | ||
| 768 | if (deobfuscatedTokens != null) { | ||
| 769 | setHighlightedTokens(deobfuscatedTokens, m_deobfuscatedHighlightPainter); | ||
| 770 | } | ||
| 771 | if (otherTokens != null) { | ||
| 772 | setHighlightedTokens(otherTokens, m_otherHighlightPainter); | ||
| 773 | } | ||
| 774 | |||
| 775 | redraw(); | ||
| 776 | } | ||
| 777 | |||
| 778 | private void setHighlightedTokens(Iterable<Token> tokens, Highlighter.HighlightPainter painter) { | ||
| 779 | for (Token token : tokens) { | ||
| 780 | try { | ||
| 781 | m_editor.getHighlighter().addHighlight(token.start, token.end, painter); | ||
| 782 | } catch (BadLocationException ex) { | ||
| 783 | throw new IllegalArgumentException(ex); | ||
| 784 | } | ||
| 785 | } | ||
| 786 | } | ||
| 787 | |||
| 788 | private void clearReference() { | ||
| 789 | m_infoPanel.removeAll(); | ||
| 790 | JLabel label = new JLabel("No identifier selected"); | ||
| 791 | GuiTricks.unboldLabel(label); | ||
| 792 | label.setHorizontalAlignment(JLabel.CENTER); | ||
| 793 | m_infoPanel.add(label); | ||
| 794 | |||
| 795 | redraw(); | ||
| 796 | } | ||
| 797 | |||
| 798 | private void showReference(EntryReference<Entry,Entry> reference) { | ||
| 799 | if (reference == null) { | ||
| 800 | clearReference(); | ||
| 801 | return; | ||
| 802 | } | ||
| 803 | |||
| 804 | m_reference = reference; | ||
| 805 | |||
| 806 | m_infoPanel.removeAll(); | ||
| 807 | if (reference.entry instanceof ClassEntry) { | ||
| 808 | showClassEntry((ClassEntry)m_reference.entry); | ||
| 809 | } else if (m_reference.entry instanceof FieldEntry) { | ||
| 810 | showFieldEntry((FieldEntry)m_reference.entry); | ||
| 811 | } else if (m_reference.entry instanceof MethodEntry) { | ||
| 812 | showMethodEntry((MethodEntry)m_reference.entry); | ||
| 813 | } else if (m_reference.entry instanceof ConstructorEntry) { | ||
| 814 | showConstructorEntry((ConstructorEntry)m_reference.entry); | ||
| 815 | } else if (m_reference.entry instanceof ArgumentEntry) { | ||
| 816 | showArgumentEntry((ArgumentEntry)m_reference.entry); | ||
| 817 | } else { | ||
| 818 | throw new Error("Unknown entry type: " + m_reference.entry.getClass().getName()); | ||
| 819 | } | ||
| 820 | |||
| 821 | redraw(); | ||
| 822 | } | ||
| 823 | |||
| 824 | private void showClassEntry(ClassEntry entry) { | ||
| 825 | addNameValue(m_infoPanel, "Class", entry.getName()); | ||
| 826 | } | ||
| 827 | |||
| 828 | private void showFieldEntry(FieldEntry entry) { | ||
| 829 | addNameValue(m_infoPanel, "Field", entry.getName()); | ||
| 830 | addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); | ||
| 831 | addNameValue(m_infoPanel, "Type", entry.getType().toString()); | ||
| 832 | } | ||
| 833 | |||
| 834 | private void showMethodEntry(MethodEntry entry) { | ||
| 835 | addNameValue(m_infoPanel, "Method", entry.getName()); | ||
| 836 | addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); | ||
| 837 | addNameValue(m_infoPanel, "Signature", entry.getSignature().toString()); | ||
| 838 | } | ||
| 839 | |||
| 840 | private void showConstructorEntry(ConstructorEntry entry) { | ||
| 841 | addNameValue(m_infoPanel, "Constructor", entry.getClassEntry().getName()); | ||
| 842 | if (!entry.isStatic()) { | ||
| 843 | addNameValue(m_infoPanel, "Signature", entry.getSignature().toString()); | ||
| 844 | } | ||
| 845 | } | ||
| 846 | |||
| 847 | private void showArgumentEntry(ArgumentEntry entry) { | ||
| 848 | addNameValue(m_infoPanel, "Argument", entry.getName()); | ||
| 849 | addNameValue(m_infoPanel, "Class", entry.getClassEntry().getName()); | ||
| 850 | addNameValue(m_infoPanel, "Method", entry.getBehaviorEntry().getName()); | ||
| 851 | addNameValue(m_infoPanel, "Index", Integer.toString(entry.getIndex())); | ||
| 852 | } | ||
| 853 | |||
| 854 | private void addNameValue(JPanel container, String name, String value) { | ||
| 855 | JPanel panel = new JPanel(); | ||
| 856 | panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); | ||
| 857 | container.add(panel); | ||
| 858 | |||
| 859 | JLabel label = new JLabel(name + ":", JLabel.RIGHT); | ||
| 860 | label.setPreferredSize(new Dimension(100, label.getPreferredSize().height)); | ||
| 861 | panel.add(label); | ||
| 862 | |||
| 863 | panel.add(GuiTricks.unboldLabel(new JLabel(value, JLabel.LEFT))); | ||
| 864 | } | ||
| 865 | |||
| 866 | private void onCaretMove(int pos) { | ||
| 867 | |||
| 868 | Token token = m_controller.getToken(pos); | ||
| 869 | boolean isToken = token != null; | ||
| 870 | |||
| 871 | m_reference = m_controller.getDeobfReference(token); | ||
| 872 | boolean isClassEntry = isToken && m_reference.entry instanceof ClassEntry; | ||
| 873 | boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; | ||
| 874 | boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; | ||
| 875 | boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; | ||
| 876 | boolean isInJar = isToken && m_controller.entryIsInJar(m_reference.entry); | ||
| 877 | boolean isRenameable = isToken && m_controller.referenceIsRenameable(m_reference); | ||
| 878 | |||
| 879 | if (isToken) { | ||
| 880 | showReference(m_reference); | ||
| 881 | } else { | ||
| 882 | clearReference(); | ||
| 883 | } | ||
| 884 | |||
| 885 | m_renameMenu.setEnabled(isRenameable && isToken); | ||
| 886 | m_showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry); | ||
| 887 | m_showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry); | ||
| 888 | m_showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry); | ||
| 889 | m_openEntryMenu.setEnabled(isInJar && (isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry)); | ||
| 890 | m_openPreviousMenu.setEnabled(m_controller.hasPreviousLocation()); | ||
| 891 | m_toggleMappingMenu.setEnabled(isRenameable && isToken); | ||
| 892 | |||
| 893 | if (isToken && m_controller.entryHasDeobfuscatedName(m_reference.entry)) { | ||
| 894 | m_toggleMappingMenu.setText("Reset to obfuscated"); | ||
| 895 | } else { | ||
| 896 | m_toggleMappingMenu.setText("Mark as deobfuscated"); | ||
| 897 | } | ||
| 898 | } | ||
| 899 | |||
| 900 | private void navigateTo(Entry entry) { | ||
| 901 | if (!m_controller.entryIsInJar(entry)) { | ||
| 902 | // entry is not in the jar. Ignore it | ||
| 903 | return; | ||
| 904 | } | ||
| 905 | if (m_reference != null) { | ||
| 906 | m_controller.savePreviousReference(m_reference); | ||
| 907 | } | ||
| 908 | m_controller.openDeclaration(entry); | ||
| 909 | } | ||
| 910 | |||
| 911 | private void navigateTo(EntryReference<Entry,Entry> reference) { | ||
| 912 | if (!m_controller.entryIsInJar(reference.getLocationClassEntry())) { | ||
| 913 | // reference is not in the jar. Ignore it | ||
| 914 | return; | ||
| 915 | } | ||
| 916 | if (m_reference != null) { | ||
| 917 | m_controller.savePreviousReference(m_reference); | ||
| 918 | } | ||
| 919 | m_controller.openReference(reference); | ||
| 920 | } | ||
| 921 | |||
| 922 | private void startRename() { | ||
| 923 | |||
| 924 | // init the text box | ||
| 925 | final JTextField text = new JTextField(); | ||
| 926 | text.setText(m_reference.getNamableName()); | ||
| 927 | text.setPreferredSize(new Dimension(360, text.getPreferredSize().height)); | ||
| 928 | text.addKeyListener(new KeyAdapter() { | ||
| 929 | @Override | ||
| 930 | public void keyPressed(KeyEvent event) { | ||
| 931 | switch (event.getKeyCode()) { | ||
| 932 | case KeyEvent.VK_ENTER: | ||
| 933 | finishRename(text, true); | ||
| 934 | break; | ||
| 935 | |||
| 936 | case KeyEvent.VK_ESCAPE: | ||
| 937 | finishRename(text, false); | ||
| 938 | break; | ||
| 939 | } | ||
| 940 | } | ||
| 941 | }); | ||
| 942 | |||
| 943 | // find the label with the name and replace it with the text box | ||
| 944 | JPanel panel = (JPanel)m_infoPanel.getComponent(0); | ||
| 945 | panel.remove(panel.getComponentCount() - 1); | ||
| 946 | panel.add(text); | ||
| 947 | text.grabFocus(); | ||
| 948 | text.selectAll(); | ||
| 949 | |||
| 950 | redraw(); | ||
| 951 | } | ||
| 952 | |||
| 953 | private void finishRename(JTextField text, boolean saveName) { | ||
| 954 | String newName = text.getText(); | ||
| 955 | if (saveName && newName != null && newName.length() > 0) { | ||
| 956 | try { | ||
| 957 | m_controller.rename(m_reference, newName); | ||
| 958 | } catch (IllegalNameException ex) { | ||
| 959 | text.setBorder(BorderFactory.createLineBorder(Color.red, 1)); | ||
| 960 | text.setToolTipText(ex.getReason()); | ||
| 961 | GuiTricks.showToolTipNow(text); | ||
| 962 | } | ||
| 963 | return; | ||
| 964 | } | ||
| 965 | |||
| 966 | // abort the rename | ||
| 967 | JPanel panel = (JPanel)m_infoPanel.getComponent(0); | ||
| 968 | panel.remove(panel.getComponentCount() - 1); | ||
| 969 | panel.add(GuiTricks.unboldLabel(new JLabel(m_reference.getNamableName(), JLabel.LEFT))); | ||
| 970 | |||
| 971 | m_editor.grabFocus(); | ||
| 972 | |||
| 973 | redraw(); | ||
| 974 | } | ||
| 975 | |||
| 976 | private void showInheritance() { | ||
| 977 | |||
| 978 | if (m_reference == null) { | ||
| 979 | return; | ||
| 980 | } | ||
| 981 | |||
| 982 | m_inheritanceTree.setModel(null); | ||
| 983 | |||
| 984 | if (m_reference.entry instanceof ClassEntry) { | ||
| 985 | // get the class inheritance | ||
| 986 | ClassInheritanceTreeNode classNode = m_controller.getClassInheritance((ClassEntry)m_reference.entry); | ||
| 987 | |||
| 988 | // show the tree at the root | ||
| 989 | TreePath path = getPathToRoot(classNode); | ||
| 990 | m_inheritanceTree.setModel(new DefaultTreeModel((TreeNode)path.getPathComponent(0))); | ||
| 991 | m_inheritanceTree.expandPath(path); | ||
| 992 | m_inheritanceTree.setSelectionRow(m_inheritanceTree.getRowForPath(path)); | ||
| 993 | } else if (m_reference.entry instanceof MethodEntry) { | ||
| 994 | // get the method inheritance | ||
| 995 | MethodInheritanceTreeNode classNode = m_controller.getMethodInheritance((MethodEntry)m_reference.entry); | ||
| 996 | |||
| 997 | // show the tree at the root | ||
| 998 | TreePath path = getPathToRoot(classNode); | ||
| 999 | m_inheritanceTree.setModel(new DefaultTreeModel((TreeNode)path.getPathComponent(0))); | ||
| 1000 | m_inheritanceTree.expandPath(path); | ||
| 1001 | m_inheritanceTree.setSelectionRow(m_inheritanceTree.getRowForPath(path)); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | m_tabs.setSelectedIndex(0); | ||
| 1005 | redraw(); | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | private void showImplementations() { | ||
| 1009 | |||
| 1010 | if (m_reference == null) { | ||
| 1011 | return; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | m_implementationsTree.setModel(null); | ||
| 1015 | |||
| 1016 | if (m_reference.entry instanceof ClassEntry) { | ||
| 1017 | // get the class implementations | ||
| 1018 | ClassImplementationsTreeNode node = m_controller.getClassImplementations((ClassEntry)m_reference.entry); | ||
| 1019 | if (node != null) { | ||
| 1020 | // show the tree at the root | ||
| 1021 | TreePath path = getPathToRoot(node); | ||
| 1022 | m_implementationsTree.setModel(new DefaultTreeModel((TreeNode)path.getPathComponent(0))); | ||
| 1023 | m_implementationsTree.expandPath(path); | ||
| 1024 | m_implementationsTree.setSelectionRow(m_implementationsTree.getRowForPath(path)); | ||
| 1025 | } | ||
| 1026 | } else if (m_reference.entry instanceof MethodEntry) { | ||
| 1027 | // get the method implementations | ||
| 1028 | MethodImplementationsTreeNode node = m_controller.getMethodImplementations((MethodEntry)m_reference.entry); | ||
| 1029 | if (node != null) { | ||
| 1030 | // show the tree at the root | ||
| 1031 | TreePath path = getPathToRoot(node); | ||
| 1032 | m_implementationsTree.setModel(new DefaultTreeModel((TreeNode)path.getPathComponent(0))); | ||
| 1033 | m_implementationsTree.expandPath(path); | ||
| 1034 | m_implementationsTree.setSelectionRow(m_implementationsTree.getRowForPath(path)); | ||
| 1035 | } | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | m_tabs.setSelectedIndex(1); | ||
| 1039 | redraw(); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | private void showCalls() { | ||
| 1043 | |||
| 1044 | if (m_reference == null) { | ||
| 1045 | return; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | if (m_reference.entry instanceof ClassEntry) { | ||
| 1049 | // look for calls to the default constructor | ||
| 1050 | // TODO: get a list of all the constructors and find calls to all of them | ||
| 1051 | BehaviorReferenceTreeNode node = m_controller.getMethodReferences(new ConstructorEntry((ClassEntry)m_reference.entry, new Signature("()V"))); | ||
| 1052 | m_callsTree.setModel(new DefaultTreeModel(node)); | ||
| 1053 | } else if (m_reference.entry instanceof FieldEntry) { | ||
| 1054 | FieldReferenceTreeNode node = m_controller.getFieldReferences((FieldEntry)m_reference.entry); | ||
| 1055 | m_callsTree.setModel(new DefaultTreeModel(node)); | ||
| 1056 | } else if (m_reference.entry instanceof MethodEntry) { | ||
| 1057 | BehaviorReferenceTreeNode node = m_controller.getMethodReferences((MethodEntry)m_reference.entry); | ||
| 1058 | m_callsTree.setModel(new DefaultTreeModel(node)); | ||
| 1059 | } else if (m_reference.entry instanceof ConstructorEntry) { | ||
| 1060 | BehaviorReferenceTreeNode node = m_controller.getMethodReferences((ConstructorEntry)m_reference.entry); | ||
| 1061 | m_callsTree.setModel(new DefaultTreeModel(node)); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | m_tabs.setSelectedIndex(2); | ||
| 1065 | redraw(); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | private void toggleMapping() { | ||
| 1069 | if (m_controller.entryHasDeobfuscatedName(m_reference.entry)) { | ||
| 1070 | m_controller.removeMapping(m_reference); | ||
| 1071 | } else { | ||
| 1072 | m_controller.markAsDeobfuscated(m_reference); | ||
| 1073 | } | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | private TreePath getPathToRoot(TreeNode node) { | ||
| 1077 | List<TreeNode> nodes = Lists.newArrayList(); | ||
| 1078 | TreeNode n = node; | ||
| 1079 | do { | ||
| 1080 | nodes.add(n); | ||
| 1081 | n = n.getParent(); | ||
| 1082 | } while (n != null); | ||
| 1083 | Collections.reverse(nodes); | ||
| 1084 | return new TreePath(nodes.toArray()); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | private void close() { | ||
| 1088 | if (!m_controller.isDirty()) { | ||
| 1089 | // everything is saved, we can exit safely | ||
| 1090 | m_frame.dispose(); | ||
| 1091 | } else { | ||
| 1092 | // ask to save before closing | ||
| 1093 | String[] options = { "Save and exit", "Discard changes", "Cancel" }; | ||
| 1094 | int response = JOptionPane.showOptionDialog(m_frame, "Your mappings have not been saved yet. Do you want to save?", "Save your changes?", JOptionPane.YES_NO_CANCEL_OPTION, | ||
| 1095 | JOptionPane.QUESTION_MESSAGE, null, options, options[2]); | ||
| 1096 | switch (response) { | ||
| 1097 | case JOptionPane.YES_OPTION: // save and exit | ||
| 1098 | if (m_mappingsFileChooser.getSelectedFile() != null || m_mappingsFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { | ||
| 1099 | try { | ||
| 1100 | m_controller.saveMappings(m_mappingsFileChooser.getSelectedFile()); | ||
| 1101 | m_frame.dispose(); | ||
| 1102 | } catch (IOException ex) { | ||
| 1103 | throw new Error(ex); | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | break; | ||
| 1107 | |||
| 1108 | case JOptionPane.NO_OPTION: | ||
| 1109 | // don't save, exit | ||
| 1110 | m_frame.dispose(); | ||
| 1111 | break; | ||
| 1112 | |||
| 1113 | // cancel means do nothing | ||
| 1114 | } | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | private void redraw() { | ||
| 1119 | m_frame.validate(); | ||
| 1120 | m_frame.repaint(); | ||
| 1121 | } | ||
| 1122 | } | ||