From 9a3e5a9d132735f818c379ba72c554362650690d Mon Sep 17 00:00:00 2001 From: lclc98 Date: Sun, 3 Jul 2016 00:05:04 +1000 Subject: Started Gui Refactor --- src/main/java/cuchaz/enigma/gui/AboutDialog.java | 70 --- src/main/java/cuchaz/enigma/gui/CrashDialog.java | 86 ---- src/main/java/cuchaz/enigma/gui/Gui.java | 561 ++++++--------------- src/main/java/cuchaz/enigma/gui/GuiController.java | 1 + .../java/cuchaz/enigma/gui/ProgressDialog.java | 100 ---- .../java/cuchaz/enigma/gui/dialog/AboutDialog.java | 70 +++ .../java/cuchaz/enigma/gui/dialog/CrashDialog.java | 87 ++++ .../cuchaz/enigma/gui/dialog/ProgressDialog.java | 101 ++++ .../java/cuchaz/enigma/gui/elements/MenuBar.java | 169 +++++++ .../cuchaz/enigma/gui/elements/PopupMenuBar.java | 82 +++ .../enigma/gui/filechooser/FileChooserFile.java | 8 + .../enigma/gui/filechooser/FileChooserFolder.java | 11 + .../java/cuchaz/enigma/gui/panels/PanelDeobf.java | 28 + .../java/cuchaz/enigma/gui/panels/PanelEditor.java | 60 +++ .../cuchaz/enigma/gui/panels/PanelIdentifier.java | 34 ++ .../java/cuchaz/enigma/gui/panels/PanelObf.java | 27 + 16 files changed, 825 insertions(+), 670 deletions(-) delete mode 100644 src/main/java/cuchaz/enigma/gui/AboutDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/CrashDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/ProgressDialog.java create mode 100644 src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java create mode 100644 src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java create mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java create mode 100644 src/main/java/cuchaz/enigma/gui/elements/MenuBar.java create mode 100644 src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java create mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java create mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java create mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java create mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java create mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java create mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelObf.java (limited to 'src') diff --git a/src/main/java/cuchaz/enigma/gui/AboutDialog.java b/src/main/java/cuchaz/enigma/gui/AboutDialog.java deleted file mode 100644 index bb12466..0000000 --- a/src/main/java/cuchaz/enigma/gui/AboutDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.gui; - -import java.awt.Color; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.FlowLayout; -import java.io.IOException; - -import javax.swing.*; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.Util; - -public class AboutDialog { - - public static void show(JFrame parent) { - // init frame - final JFrame frame = new JFrame(Constants.NAME + " - About"); - final Container pane = frame.getContentPane(); - pane.setLayout(new FlowLayout()); - - // load the content - try { - String html = Util.readResourceToString("/about.html"); - html = String.format(html, Constants.NAME, Constants.VERSION); - JLabel label = new JLabel(html); - label.setHorizontalAlignment(JLabel.CENTER); - pane.add(label); - } catch (IOException ex) { - throw new Error(ex); - } - - // show the link - String html = "%s"; - html = String.format(html, Constants.URL, Constants.URL); - JButton link = new JButton(html); - link.addActionListener(event -> Util.openUrl(Constants.URL)); - link.setBorderPainted(false); - link.setOpaque(false); - link.setBackground(Color.WHITE); - link.setCursor(new Cursor(Cursor.HAND_CURSOR)); - link.setFocusable(false); - JPanel linkPanel = new JPanel(); - linkPanel.add(link); - pane.add(linkPanel); - - // show ok button - JButton okButton = new JButton("Ok"); - pane.add(okButton); - okButton.addActionListener(arg0 -> frame.dispose()); - - // show the frame - pane.doLayout(); - frame.setSize(400, 220); - frame.setResizable(false); - frame.setLocationRelativeTo(parent); - frame.setVisible(true); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/CrashDialog.java b/src/main/java/cuchaz/enigma/gui/CrashDialog.java deleted file mode 100644 index 3806f54..0000000 --- a/src/main/java/cuchaz/enigma/gui/CrashDialog.java +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.gui; - -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.FlowLayout; -import java.io.PrintWriter; -import java.io.StringWriter; - -import javax.swing.*; - -import cuchaz.enigma.Constants; - -public class CrashDialog { - - private static CrashDialog m_instance = null; - - private JFrame m_frame; - private JTextArea m_text; - - private CrashDialog(JFrame parent) { - // init frame - m_frame = new JFrame(Constants.NAME + " - Crash Report"); - final Container pane = m_frame.getContentPane(); - pane.setLayout(new BorderLayout()); - - JLabel label = new JLabel(Constants.NAME + " has crashed! =("); - label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - pane.add(label, BorderLayout.NORTH); - - // report panel - m_text = new JTextArea(); - m_text.setTabSize(2); - pane.add(new JScrollPane(m_text), BorderLayout.CENTER); - - // buttons panel - JPanel buttonsPanel = new JPanel(); - FlowLayout buttonsLayout = new FlowLayout(); - buttonsLayout.setAlignment(FlowLayout.RIGHT); - buttonsPanel.setLayout(buttonsLayout); - buttonsPanel.add(GuiTricks.unboldLabel(new JLabel("If you choose exit, you will lose any unsaved work."))); - JButton ignoreButton = new JButton("Ignore"); - ignoreButton.addActionListener(event -> { - // close (hide) the dialog - m_frame.setVisible(false); - }); - buttonsPanel.add(ignoreButton); - JButton exitButton = new JButton("Exit"); - exitButton.addActionListener(event -> { - // exit enigma - System.exit(1); - }); - buttonsPanel.add(exitButton); - pane.add(buttonsPanel, BorderLayout.SOUTH); - - // show the frame - m_frame.setSize(600, 400); - m_frame.setLocationRelativeTo(parent); - m_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - } - - public static void init(JFrame parent) { - m_instance = new CrashDialog(parent); - } - - public static void show(Throwable ex) { - // get the error report - StringWriter buf = new StringWriter(); - ex.printStackTrace(new PrintWriter(buf)); - String report = buf.toString(); - - // show it! - m_instance.m_text.setText(report); - m_instance.m_frame.doLayout(); - m_instance.m_frame.setVisible(true); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java index fee9c9f..623e12e 100644 --- a/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/src/main/java/cuchaz/enigma/gui/Gui.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Vector; -import java.util.jar.JarFile; import javax.swing.*; import javax.swing.text.BadLocationException; @@ -32,21 +31,33 @@ import javax.swing.tree.TreePath; import cuchaz.enigma.Constants; import cuchaz.enigma.ExceptionIgnorer; import cuchaz.enigma.analysis.*; +import cuchaz.enigma.gui.dialog.CrashDialog; +import cuchaz.enigma.gui.elements.MenuBar; +import cuchaz.enigma.gui.elements.PopupMenuBar; +import cuchaz.enigma.gui.filechooser.FileChooserFile; +import cuchaz.enigma.gui.filechooser.FileChooserFolder; +import cuchaz.enigma.gui.panels.PanelDeobf; +import cuchaz.enigma.gui.panels.PanelEditor; +import cuchaz.enigma.gui.panels.PanelIdentifier; +import cuchaz.enigma.gui.panels.PanelObf; import cuchaz.enigma.mapping.*; import de.sciss.syntaxpane.DefaultSyntaxKit; public class Gui { - private GuiController m_controller; + private GuiController controller; - // controls - private JFrame m_frame; - private ClassSelector m_obfClasses; - private ClassSelector m_deobfClasses; - private JEditorPane m_editor; - private JPanel m_classesPanel; + private final PanelObf obfPanel; + private final PanelDeobf deobfPanel; + + private final MenuBar menuBar; + public final PopupMenuBar popupMenu; + + private JFrame frame; + private PanelEditor editor; + private JPanel classesPanel; private JSplitPane m_splitClasses; - private JPanel m_infoPanel; + private PanelIdentifier m_infoPanel; private ObfuscatedHighlightPainter m_obfuscatedHighlightPainter; private DeobfuscatedHighlightPainter m_deobfuscatedHighlightPainter; private OtherHighlightPainter m_otherHighlightPainter; @@ -57,42 +68,26 @@ public class Gui { private JList m_tokens; private JTabbedPane m_tabs; - // dynamic menu items - private JMenuItem m_closeJarMenu; - private JMenuItem m_openMappingsMenu; - private JMenuItem m_openOldMappingsMenu; - private JMenuItem m_saveMappingsMenu; - private JMenuItem m_saveMappingsAsMenu; - private JMenuItem m_closeMappingsMenu; - private JMenuItem m_renameMenu; - private JMenuItem m_showInheritanceMenu; - private JMenuItem m_openEntryMenu; - private JMenuItem m_openPreviousMenu; - private JMenuItem m_showCallsMenu; - private JMenuItem m_showImplementationsMenu; - private JMenuItem m_toggleMappingMenu; - private JMenuItem m_exportSourceMenu; - private JMenuItem m_exportJarMenu; - // state - private EntryReference m_reference; - private JFileChooser m_jarFileChooser; - private JFileChooser m_mappingsFileChooser; - private JFileChooser m_oldMappingsFileChooser; + public EntryReference m_reference; - private JFileChooser m_exportSourceFileChooser; - private JFileChooser m_exportJarFileChooser; + public JFileChooser jarFileChooser; + public JFileChooser mappingsFileChooser; + public JFileChooser oldMappingsFileChooser; + + public JFileChooser exportSourceFileChooser; + public JFileChooser exportJarFileChooser; public Gui() { // init frame - m_frame = new JFrame(Constants.NAME); - final Container pane = m_frame.getContentPane(); + this.frame = new JFrame(Constants.NAME); + final Container pane = this.frame.getContentPane(); pane.setLayout(new BorderLayout()); if (Boolean.parseBoolean(System.getProperty("enigma.catchExceptions", "true"))) { // install a global exception handler to the event thread - CrashDialog.init(m_frame); + CrashDialog.init(this.frame); Thread.setDefaultUncaughtExceptionHandler((thread, t) -> { t.printStackTrace(System.err); if (!ExceptionIgnorer.shouldIgnore(t)) { @@ -101,50 +96,30 @@ public class Gui { }); } - m_controller = new GuiController(this); + this.controller = new GuiController(this); // init file choosers - m_jarFileChooser = new JFileChooser(); - m_mappingsFileChooser = new JFileChooser(); - m_mappingsFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - m_mappingsFileChooser.setAcceptAllFileFilterUsed(false); - - m_oldMappingsFileChooser = new JFileChooser(); - m_exportSourceFileChooser = new JFileChooser(); - m_exportSourceFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - m_exportJarFileChooser = new JFileChooser(); - - // init obfuscated classes list - m_obfClasses = new ClassSelector(ClassSelector.ObfuscatedClassEntryComparator); - m_obfClasses.setListener(this::navigateTo); - JScrollPane obfScroller = new JScrollPane(m_obfClasses); - JPanel obfPanel = new JPanel(); - obfPanel.setLayout(new BorderLayout()); - obfPanel.add(new JLabel("Obfuscated Classes"), BorderLayout.NORTH); - obfPanel.add(obfScroller, BorderLayout.CENTER); - - // init deobfuscated classes list - m_deobfClasses = new ClassSelector(ClassSelector.DeobfuscatedClassEntryComparator); - m_deobfClasses.setListener(this::navigateTo); - JScrollPane deobfScroller = new JScrollPane(m_deobfClasses); - JPanel deobfPanel = new JPanel(); - deobfPanel.setLayout(new BorderLayout()); - deobfPanel.add(new JLabel("De-obfuscated Classes"), BorderLayout.NORTH); - deobfPanel.add(deobfScroller, BorderLayout.CENTER); + this.jarFileChooser = new FileChooserFile(); + this.mappingsFileChooser = new FileChooserFolder(); + + + this.oldMappingsFileChooser = new FileChooserFile(); + this.exportSourceFileChooser = new FileChooserFolder(); + this.exportJarFileChooser = new FileChooserFile(); + + this.obfPanel = new PanelObf(this); + this.deobfPanel = new PanelDeobf(this); // set up classes panel (don't add the splitter yet) - m_splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel); + m_splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, this.obfPanel, this.deobfPanel); m_splitClasses.setResizeWeight(0.3); - m_classesPanel = new JPanel(); - m_classesPanel.setLayout(new BorderLayout()); - m_classesPanel.setPreferredSize(new Dimension(250, 0)); + this.classesPanel = new JPanel(); + this.classesPanel.setLayout(new BorderLayout()); + this.classesPanel.setPreferredSize(new Dimension(250, 0)); // init info panel - m_infoPanel = new JPanel(); - m_infoPanel.setLayout(new GridLayout(4, 1, 0, 0)); - m_infoPanel.setPreferredSize(new Dimension(0, 100)); - m_infoPanel.setBorder(BorderFactory.createTitledBorder("Identifier Info")); - clearReference(); + m_infoPanel = new PanelIdentifier(this); + m_infoPanel.clearReference(); // init editor DefaultSyntaxKit.initKit(); @@ -152,110 +127,12 @@ public class Gui { m_deobfuscatedHighlightPainter = new DeobfuscatedHighlightPainter(); m_otherHighlightPainter = new OtherHighlightPainter(); m_selectionHighlightPainter = new SelectionHighlightPainter(); - m_editor = new JEditorPane(); - m_editor.setEditable(false); - m_editor.setCaret(new BrowserCaret()); - JScrollPane sourceScroller = new JScrollPane(m_editor); - m_editor.setContentType("text/java"); - m_editor.addCaretListener(event -> onCaretMove(event.getDot())); - m_editor.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.VK_R: - m_renameMenu.doClick(); - break; - - case KeyEvent.VK_I: - m_showInheritanceMenu.doClick(); - break; - - case KeyEvent.VK_M: - m_showImplementationsMenu.doClick(); - break; - - case KeyEvent.VK_N: - m_openEntryMenu.doClick(); - break; - - case KeyEvent.VK_P: - m_openPreviousMenu.doClick(); - break; - - case KeyEvent.VK_C: - m_showCallsMenu.doClick(); - break; - - case KeyEvent.VK_T: - m_toggleMappingMenu.doClick(); - break; - } - } - }); - - // turn off token highlighting (it's wrong most of the time anyway...) - DefaultSyntaxKit kit = (DefaultSyntaxKit) m_editor.getEditorKit(); - kit.toggleComponent(m_editor, "de.sciss.syntaxpane.components.TokenMarker"); + this.editor = new PanelEditor(this); + JScrollPane sourceScroller = new JScrollPane(this.editor); // init editor popup menu - JPopupMenu popupMenu = new JPopupMenu(); - m_editor.setComponentPopupMenu(popupMenu); - { - JMenuItem menu = new JMenuItem("Rename"); - menu.addActionListener(event -> startRename()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_renameMenu = menu; - } - { - JMenuItem menu = new JMenuItem("Show Inheritance"); - menu.addActionListener(event -> showInheritance()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_showInheritanceMenu = menu; - } - { - JMenuItem menu = new JMenuItem("Show Implementations"); - menu.addActionListener(event -> showImplementations()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_showImplementationsMenu = menu; - } - { - JMenuItem menu = new JMenuItem("Show Calls"); - menu.addActionListener(event -> showCalls()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_showCallsMenu = menu; - } - { - JMenuItem menu = new JMenuItem("Go to Declaration"); - menu.addActionListener(event -> navigateTo(m_reference.entry)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_openEntryMenu = menu; - } - { - JMenuItem menu = new JMenuItem("Go to previous"); - menu.addActionListener(event -> m_controller.openPreviousReference()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_openPreviousMenu = menu; - } - { - JMenuItem menu = new JMenuItem("Mark as deobfuscated"); - menu.addActionListener(event -> toggleMapping()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0)); - menu.setEnabled(false); - popupMenu.add(menu); - m_toggleMappingMenu = menu; - } + this.popupMenu = new PopupMenuBar(this); + this.editor.setComponentPopupMenu(this.popupMenu); // init inheritance panel m_inheritanceTree = new JTree(); @@ -342,7 +219,7 @@ public class Gui { } }); m_tokens = new JList<>(); - m_tokens.setCellRenderer(new TokenListCellRenderer(m_controller)); + m_tokens.setCellRenderer(new TokenListCellRenderer(this.controller)); m_tokens.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); m_tokens.setLayoutOrientation(JList.VERTICAL); m_tokens.addMouseListener(new MouseAdapter() { @@ -380,152 +257,18 @@ public class Gui { JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, m_tabs); splitRight.setResizeWeight(1); // let the left side take all the slack splitRight.resetToPreferredSizes(); - JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, m_classesPanel, splitRight); + JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.classesPanel, splitRight); splitCenter.setResizeWeight(0); // let the right side take all the slack pane.add(splitCenter, BorderLayout.CENTER); // init menus - JMenuBar menuBar = new JMenuBar(); - m_frame.setJMenuBar(menuBar); - { - JMenu menu = new JMenu("File"); - menuBar.add(menu); - { - JMenuItem item = new JMenuItem("Open Jar..."); - menu.add(item); - item.addActionListener(event -> { - if (m_jarFileChooser.showOpenDialog(m_frame) == JFileChooser.APPROVE_OPTION) { - // load the jar in a separate thread - new Thread() { - @Override - public void run() { - try { - m_controller.openJar(new JarFile(m_jarFileChooser.getSelectedFile())); - } catch (IOException ex) { - throw new Error(ex); - } - } - }.start(); - } - }); - } - { - JMenuItem item = new JMenuItem("Close Jar"); - menu.add(item); - item.addActionListener(event -> m_controller.closeJar()); - m_closeJarMenu = item; - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem("Open Mappings..."); - menu.add(item); - item.addActionListener(event -> { - if (m_mappingsFileChooser.showOpenDialog(m_frame) == JFileChooser.APPROVE_OPTION) { - try { - m_controller.openMappings(m_mappingsFileChooser.getSelectedFile()); - } catch (IOException ex) { - throw new Error(ex); - } catch (MappingParseException ex) { - JOptionPane.showMessageDialog(m_frame, ex.getMessage()); - } - } - }); - m_openMappingsMenu = item; - } - { - JMenuItem item = new JMenuItem("Open Old Mappings..."); - menu.add(item); - item.addActionListener(event -> { - if (m_oldMappingsFileChooser.showOpenDialog(m_frame) == JFileChooser.APPROVE_OPTION) { - try { - m_controller.openOldMappings(m_oldMappingsFileChooser.getSelectedFile()); - } catch (IOException ex) { - throw new Error(ex); - } catch (MappingParseException ex) { - JOptionPane.showMessageDialog(m_frame, ex.getMessage()); - } - } - }); - m_openOldMappingsMenu = item; - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem("Save Mappings"); - menu.add(item); - item.addActionListener(event -> { - try { - m_controller.saveMappings(m_mappingsFileChooser.getSelectedFile()); - } catch (IOException ex) { - throw new Error(ex); - } - }); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); - m_saveMappingsMenu = item; - } - { - JMenuItem item = new JMenuItem("Save Mappings As..."); - menu.add(item); - item.addActionListener(event -> { - if (m_mappingsFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { - try { - m_controller.saveMappings(m_mappingsFileChooser.getSelectedFile()); - m_saveMappingsMenu.setEnabled(true); - } catch (IOException ex) { - throw new Error(ex); - } - } - }); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); - m_saveMappingsAsMenu = item; - } - { - JMenuItem item = new JMenuItem("Close Mappings"); - menu.add(item); - item.addActionListener(event -> m_controller.closeMappings()); - m_closeMappingsMenu = item; - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem("Export Source..."); - menu.add(item); - item.addActionListener(event -> { - if (m_exportSourceFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { - m_controller.exportSource(m_exportSourceFileChooser.getSelectedFile()); - } - }); - m_exportSourceMenu = item; - } - { - JMenuItem item = new JMenuItem("Export Jar..."); - menu.add(item); - item.addActionListener(event -> { - if (m_exportJarFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { - m_controller.exportJar(m_exportJarFileChooser.getSelectedFile()); - } - }); - m_exportJarMenu = item; - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem("Exit"); - menu.add(item); - item.addActionListener(event -> close()); - } - } - { - JMenu menu = new JMenu("Help"); - menuBar.add(menu); - { - JMenuItem item = new JMenuItem("About"); - menu.add(item); - item.addActionListener(event -> AboutDialog.show(m_frame)); - } - } + this.menuBar = new MenuBar(this); + this.frame.setJMenuBar(this.menuBar); // init state onCloseJar(); - m_frame.addWindowListener(new WindowAdapter() { + this.frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent event) { close(); @@ -534,93 +277,93 @@ public class Gui { // show the frame pane.doLayout(); - m_frame.setSize(1024, 576); - m_frame.setMinimumSize(new Dimension(640, 480)); - m_frame.setVisible(true); - m_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + this.frame.setSize(1024, 576); + this.frame.setMinimumSize(new Dimension(640, 480)); + this.frame.setVisible(true); + this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); } public JFrame getFrame() { - return m_frame; + return this.frame; } public GuiController getController() { - return m_controller; + return this.controller; } public void onStartOpenJar() { - m_classesPanel.removeAll(); + this.classesPanel.removeAll(); JPanel panel = new JPanel(); panel.setLayout(new FlowLayout()); panel.add(new JLabel("Loading...")); - m_classesPanel.add(panel); + this.classesPanel.add(panel); redraw(); } public void onFinishOpenJar(String jarName) { // update gui - m_frame.setTitle(Constants.NAME + " - " + jarName); - m_classesPanel.removeAll(); - m_classesPanel.add(m_splitClasses); + this.frame.setTitle(Constants.NAME + " - " + jarName); + this.classesPanel.removeAll(); + this.classesPanel.add(m_splitClasses); setSource(null); // update menu - m_closeJarMenu.setEnabled(true); - m_openOldMappingsMenu.setEnabled(true); - m_openMappingsMenu.setEnabled(true); - m_saveMappingsMenu.setEnabled(false); - m_saveMappingsAsMenu.setEnabled(true); - m_closeMappingsMenu.setEnabled(true); - m_exportSourceMenu.setEnabled(true); - m_exportJarMenu.setEnabled(true); + this.menuBar.closeJarMenu.setEnabled(true); + this.menuBar.openOldMappingsMenu.setEnabled(true); + this.menuBar.openMappingsMenu.setEnabled(true); + this.menuBar.saveMappingsMenu.setEnabled(false); + this.menuBar.saveMappingsAsMenu.setEnabled(true); + this.menuBar.closeMappingsMenu.setEnabled(true); + this.menuBar.exportSourceMenu.setEnabled(true); + this.menuBar.exportJarMenu.setEnabled(true); redraw(); } public void onCloseJar() { // update gui - m_frame.setTitle(Constants.NAME); + this.frame.setTitle(Constants.NAME); setObfClasses(null); setDeobfClasses(null); setSource(null); - m_classesPanel.removeAll(); + this.classesPanel.removeAll(); // update menu - m_closeJarMenu.setEnabled(false); - m_openOldMappingsMenu.setEnabled(false); - m_openMappingsMenu.setEnabled(false); - m_saveMappingsMenu.setEnabled(false); - m_saveMappingsAsMenu.setEnabled(false); - m_closeMappingsMenu.setEnabled(false); - m_exportSourceMenu.setEnabled(false); - m_exportJarMenu.setEnabled(false); + this.menuBar.closeJarMenu.setEnabled(false); + this.menuBar.openOldMappingsMenu.setEnabled(false); + this.menuBar.openMappingsMenu.setEnabled(false); + this.menuBar.saveMappingsMenu.setEnabled(false); + this.menuBar.saveMappingsAsMenu.setEnabled(false); + this.menuBar.closeMappingsMenu.setEnabled(false); + this.menuBar.exportSourceMenu.setEnabled(false); + this.menuBar.exportJarMenu.setEnabled(false); redraw(); } public void setObfClasses(Collection obfClasses) { - m_obfClasses.setClasses(obfClasses); + this.obfPanel.obfClasses.setClasses(obfClasses); } public void setDeobfClasses(Collection deobfClasses) { - m_deobfClasses.setClasses(deobfClasses); + this.deobfPanel.deobfClasses.setClasses(deobfClasses); } public void setMappingsFile(File file) { - m_mappingsFileChooser.setSelectedFile(file); - m_saveMappingsMenu.setEnabled(file != null); + this.mappingsFileChooser.setSelectedFile(file); + this.menuBar.saveMappingsMenu.setEnabled(file != null); } public void setSource(String source) { - m_editor.getHighlighter().removeAllHighlights(); - m_editor.setText(source); + this.editor.getHighlighter().removeAllHighlights(); + this.editor.setText(source); } public void showToken(final Token token) { if (token == null) { throw new IllegalArgumentException("Token cannot be null!"); } - CodeReader.navigateToToken(m_editor, token, m_selectionHighlightPainter); + CodeReader.navigateToToken(this.editor, token, m_selectionHighlightPainter); redraw(); } @@ -642,7 +385,7 @@ public class Gui { public void setHighlightedTokens(Iterable obfuscatedTokens, Iterable deobfuscatedTokens, Iterable otherTokens) { // remove any old highlighters - m_editor.getHighlighter().removeAllHighlights(); + this.editor.getHighlighter().removeAllHighlights(); // color things based on the index if (obfuscatedTokens != null) { @@ -661,26 +404,16 @@ public class Gui { private void setHighlightedTokens(Iterable tokens, Highlighter.HighlightPainter painter) { for (Token token : tokens) { try { - m_editor.getHighlighter().addHighlight(token.start, token.end, painter); + this.editor.getHighlighter().addHighlight(token.start, token.end, painter); } catch (BadLocationException ex) { throw new IllegalArgumentException(ex); } } } - private void clearReference() { - m_infoPanel.removeAll(); - JLabel label = new JLabel("No identifier selected"); - GuiTricks.unboldLabel(label); - label.setHorizontalAlignment(JLabel.CENTER); - m_infoPanel.add(label); - - redraw(); - } - private void showReference(EntryReference reference) { if (reference == null) { - clearReference(); + m_infoPanel.clearReference(); return; } @@ -746,63 +479,63 @@ public class Gui { panel.add(GuiTricks.unboldLabel(new JLabel(value, JLabel.LEFT))); } - private void onCaretMove(int pos) { + public void onCaretMove(int pos) { - Token token = m_controller.getToken(pos); + Token token = this.controller.getToken(pos); boolean isToken = token != null; - m_reference = m_controller.getDeobfReference(token); + m_reference = this.controller.getDeobfReference(token); boolean isClassEntry = isToken && m_reference.entry instanceof ClassEntry; boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; - boolean isInJar = isToken && m_controller.entryIsInJar(m_reference.entry); - boolean isRenameable = isToken && m_controller.referenceIsRenameable(m_reference); + boolean isInJar = isToken && this.controller.entryIsInJar(m_reference.entry); + boolean isRenameable = isToken && this.controller.referenceIsRenameable(m_reference); if (isToken) { showReference(m_reference); } else { - clearReference(); + m_infoPanel.clearReference(); } - m_renameMenu.setEnabled(isRenameable && isToken); - m_showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry); - m_showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry); - m_showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry); - m_openEntryMenu.setEnabled(isInJar && (isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry)); - m_openPreviousMenu.setEnabled(m_controller.hasPreviousLocation()); - m_toggleMappingMenu.setEnabled(isRenameable && isToken); + this.popupMenu.renameMenu.setEnabled(isRenameable && isToken); + this.popupMenu.showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry); + this.popupMenu.showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry); + this.popupMenu.showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry); + this.popupMenu.openEntryMenu.setEnabled(isInJar && (isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry)); + this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousLocation()); + this.popupMenu.toggleMappingMenu.setEnabled(isRenameable && isToken); - if (isToken && m_controller.entryHasDeobfuscatedName(m_reference.entry)) { - m_toggleMappingMenu.setText("Reset to obfuscated"); + if (isToken && this.controller.entryHasDeobfuscatedName(m_reference.entry)) { + this.popupMenu.toggleMappingMenu.setText("Reset to obfuscated"); } else { - m_toggleMappingMenu.setText("Mark as deobfuscated"); + this.popupMenu.toggleMappingMenu.setText("Mark as deobfuscated"); } } - private void navigateTo(Entry entry) { - if (!m_controller.entryIsInJar(entry)) { + public void navigateTo(Entry entry) { + if (!this.controller.entryIsInJar(entry)) { // entry is not in the jar. Ignore it return; } if (m_reference != null) { - m_controller.savePreviousReference(m_reference); + this.controller.savePreviousReference(m_reference); } - m_controller.openDeclaration(entry); + this.controller.openDeclaration(entry); } private void navigateTo(EntryReference reference) { - if (!m_controller.entryIsInJar(reference.getLocationClassEntry())) { + if (!this.controller.entryIsInJar(reference.getLocationClassEntry())) { // reference is not in the jar. Ignore it return; } if (m_reference != null) { - m_controller.savePreviousReference(m_reference); + this.controller.savePreviousReference(m_reference); } - m_controller.openReference(reference); + this.controller.openReference(reference); } - private void startRename() { + public void startRename() { // init the text box final JTextField text = new JTextField(); @@ -837,7 +570,7 @@ public class Gui { String newName = text.getText(); if (saveName && newName != null && newName.length() > 0) { try { - m_controller.rename(m_reference, newName); + this.controller.rename(m_reference, newName); } catch (IllegalNameException ex) { text.setBorder(BorderFactory.createLineBorder(Color.red, 1)); text.setToolTipText(ex.getReason()); @@ -851,12 +584,12 @@ public class Gui { panel.remove(panel.getComponentCount() - 1); panel.add(GuiTricks.unboldLabel(new JLabel(m_reference.getNamableName(), JLabel.LEFT))); - m_editor.grabFocus(); + this.editor.grabFocus(); redraw(); } - private void showInheritance() { + public void showInheritance() { if (m_reference == null) { return; @@ -866,7 +599,7 @@ public class Gui { if (m_reference.entry instanceof ClassEntry) { // get the class inheritance - ClassInheritanceTreeNode classNode = m_controller.getClassInheritance((ClassEntry) m_reference.entry); + ClassInheritanceTreeNode classNode = this.controller.getClassInheritance((ClassEntry) m_reference.entry); // show the tree at the root TreePath path = getPathToRoot(classNode); @@ -875,7 +608,7 @@ public class Gui { m_inheritanceTree.setSelectionRow(m_inheritanceTree.getRowForPath(path)); } else if (m_reference.entry instanceof MethodEntry) { // get the method inheritance - MethodInheritanceTreeNode classNode = m_controller.getMethodInheritance((MethodEntry) m_reference.entry); + MethodInheritanceTreeNode classNode = this.controller.getMethodInheritance((MethodEntry) m_reference.entry); // show the tree at the root TreePath path = getPathToRoot(classNode); @@ -888,7 +621,7 @@ public class Gui { redraw(); } - private void showImplementations() { + public void showImplementations() { if (m_reference == null) { return; @@ -898,7 +631,7 @@ public class Gui { if (m_reference.entry instanceof ClassEntry) { // get the class implementations - ClassImplementationsTreeNode node = m_controller.getClassImplementations((ClassEntry) m_reference.entry); + ClassImplementationsTreeNode node = this.controller.getClassImplementations((ClassEntry) m_reference.entry); if (node != null) { // show the tree at the root TreePath path = getPathToRoot(node); @@ -908,7 +641,7 @@ public class Gui { } } else if (m_reference.entry instanceof MethodEntry) { // get the method implementations - MethodImplementationsTreeNode node = m_controller.getMethodImplementations((MethodEntry) m_reference.entry); + MethodImplementationsTreeNode node = this.controller.getMethodImplementations((MethodEntry) m_reference.entry); if (node != null) { // show the tree at the root TreePath path = getPathToRoot(node); @@ -922,7 +655,7 @@ public class Gui { redraw(); } - private void showCalls() { + public void showCalls() { if (m_reference == null) { return; @@ -931,16 +664,16 @@ public class Gui { if (m_reference.entry instanceof ClassEntry) { // look for calls to the default constructor // TODO: get a list of all the constructors and find calls to all of them - BehaviorReferenceTreeNode node = m_controller.getMethodReferences(new ConstructorEntry((ClassEntry) m_reference.entry, new Signature("()V"))); + BehaviorReferenceTreeNode node = this.controller.getMethodReferences(new ConstructorEntry((ClassEntry) m_reference.entry, new Signature("()V"))); m_callsTree.setModel(new DefaultTreeModel(node)); } else if (m_reference.entry instanceof FieldEntry) { - FieldReferenceTreeNode node = m_controller.getFieldReferences((FieldEntry) m_reference.entry); + FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) m_reference.entry); m_callsTree.setModel(new DefaultTreeModel(node)); } else if (m_reference.entry instanceof MethodEntry) { - BehaviorReferenceTreeNode node = m_controller.getMethodReferences((MethodEntry) m_reference.entry); + BehaviorReferenceTreeNode node = this.controller.getMethodReferences((MethodEntry) m_reference.entry); m_callsTree.setModel(new DefaultTreeModel(node)); } else if (m_reference.entry instanceof ConstructorEntry) { - BehaviorReferenceTreeNode node = m_controller.getMethodReferences((ConstructorEntry) m_reference.entry); + BehaviorReferenceTreeNode node = this.controller.getMethodReferences((ConstructorEntry) m_reference.entry); m_callsTree.setModel(new DefaultTreeModel(node)); } @@ -948,11 +681,11 @@ public class Gui { redraw(); } - private void toggleMapping() { - if (m_controller.entryHasDeobfuscatedName(m_reference.entry)) { - m_controller.removeMapping(m_reference); + public void toggleMapping() { + if (this.controller.entryHasDeobfuscatedName(m_reference.entry)) { + this.controller.removeMapping(m_reference); } else { - m_controller.markAsDeobfuscated(m_reference); + this.controller.markAsDeobfuscated(m_reference); } } @@ -967,21 +700,21 @@ public class Gui { return new TreePath(nodes.toArray()); } - private void close() { - if (!m_controller.isDirty()) { + public void close() { + if (!this.controller.isDirty()) { // everything is saved, we can exit safely - m_frame.dispose(); + this.frame.dispose(); } else { // ask to save before closing String[] options = {"Save and exit", "Discard changes", "Cancel"}; - 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, + int response = JOptionPane.showOptionDialog(this.frame, "Your mappings have not been saved yet. Do you want to save?", "Save your changes?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2]); switch (response) { case JOptionPane.YES_OPTION: // save and exit - if (m_mappingsFileChooser.getSelectedFile() != null || m_mappingsFileChooser.showSaveDialog(m_frame) == JFileChooser.APPROVE_OPTION) { + if (this.mappingsFileChooser.getSelectedFile() != null || this.mappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION) { try { - m_controller.saveMappings(m_mappingsFileChooser.getCurrentDirectory()); - m_frame.dispose(); + this.controller.saveMappings(this.mappingsFileChooser.getCurrentDirectory()); + this.frame.dispose(); } catch (IOException ex) { throw new Error(ex); } @@ -990,7 +723,7 @@ public class Gui { case JOptionPane.NO_OPTION: // don't save, exit - m_frame.dispose(); + this.frame.dispose(); break; // cancel means do nothing @@ -998,8 +731,8 @@ public class Gui { } } - private void redraw() { - m_frame.validate(); - m_frame.repaint(); + public void redraw() { + this.frame.validate(); + this.frame.repaint(); } } diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java index 868e0d4..37244ff 100644 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/src/main/java/cuchaz/enigma/gui/GuiController.java @@ -25,6 +25,7 @@ import java.util.jar.JarFile; import cuchaz.enigma.Deobfuscator; import cuchaz.enigma.analysis.*; +import cuchaz.enigma.gui.dialog.ProgressDialog; import cuchaz.enigma.mapping.*; public class GuiController { diff --git a/src/main/java/cuchaz/enigma/gui/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/ProgressDialog.java deleted file mode 100644 index 70bca15..0000000 --- a/src/main/java/cuchaz/enigma/gui/ProgressDialog.java +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ -package cuchaz.enigma.gui; - -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; - -import javax.swing.*; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.Deobfuscator.ProgressListener; - -public class ProgressDialog implements ProgressListener, AutoCloseable { - - private JFrame frame; - private JLabel labelTitle; - private JLabel labelText; - private JProgressBar progress; - - public ProgressDialog(JFrame parent) { - - // init frame - this.frame = new JFrame(Constants.NAME + " - Operation in progress"); - final Container pane = this.frame.getContentPane(); - FlowLayout layout = new FlowLayout(); - layout.setAlignment(FlowLayout.LEFT); - pane.setLayout(layout); - - this.labelTitle = new JLabel(); - pane.add(this.labelTitle); - - // set up the progress bar - JPanel panel = new JPanel(); - pane.add(panel); - panel.setLayout(new BorderLayout()); - this.labelText = GuiTricks.unboldLabel(new JLabel()); - this.progress = new JProgressBar(); - this.labelText.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - panel.add(this.labelText, BorderLayout.NORTH); - panel.add(this.progress, BorderLayout.CENTER); - panel.setPreferredSize(new Dimension(360, 50)); - - // show the frame - pane.doLayout(); - this.frame.setSize(400, 120); - this.frame.setResizable(false); - this.frame.setLocationRelativeTo(parent); - this.frame.setVisible(true); - this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - } - - public void close() { - this.frame.dispose(); - } - - @Override - public void init(int totalWork, String title) { - this.labelTitle.setText(title); - this.progress.setMinimum(0); - this.progress.setMaximum(totalWork); - this.progress.setValue(0); - } - - @Override - public void onProgress(int numDone, String message) { - this.labelText.setText(message); - this.progress.setValue(numDone); - - // update the frame - this.frame.validate(); - this.frame.repaint(); - } - - public interface ProgressRunnable { - void run(ProgressListener listener) throws Exception; - } - - public static void runInThread(final JFrame parent, final ProgressRunnable runnable) { - new Thread() { - @Override - public void run() { - try (ProgressDialog progress = new ProgressDialog(parent)) { - runnable.run(progress); - } catch (Exception ex) { - throw new Error(ex); - } - } - }.start(); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java new file mode 100644 index 0000000..da4f5fb --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.gui.dialog; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.FlowLayout; +import java.io.IOException; + +import javax.swing.*; + +import cuchaz.enigma.Constants; +import cuchaz.enigma.Util; + +public class AboutDialog { + + public static void show(JFrame parent) { + // init frame + final JFrame frame = new JFrame(Constants.NAME + " - About"); + final Container pane = frame.getContentPane(); + pane.setLayout(new FlowLayout()); + + // load the content + try { + String html = Util.readResourceToString("/about.html"); + html = String.format(html, Constants.NAME, Constants.VERSION); + JLabel label = new JLabel(html); + label.setHorizontalAlignment(JLabel.CENTER); + pane.add(label); + } catch (IOException ex) { + throw new Error(ex); + } + + // show the link + String html = "%s"; + html = String.format(html, Constants.URL, Constants.URL); + JButton link = new JButton(html); + link.addActionListener(event -> Util.openUrl(Constants.URL)); + link.setBorderPainted(false); + link.setOpaque(false); + link.setBackground(Color.WHITE); + link.setCursor(new Cursor(Cursor.HAND_CURSOR)); + link.setFocusable(false); + JPanel linkPanel = new JPanel(); + linkPanel.add(link); + pane.add(linkPanel); + + // show ok button + JButton okButton = new JButton("Ok"); + pane.add(okButton); + okButton.addActionListener(arg0 -> frame.dispose()); + + // show the frame + pane.doLayout(); + frame.setSize(400, 220); + frame.setResizable(false); + frame.setLocationRelativeTo(parent); + frame.setVisible(true); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + } +} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java new file mode 100644 index 0000000..71aab01 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.gui.dialog; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.FlowLayout; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.swing.*; + +import cuchaz.enigma.Constants; +import cuchaz.enigma.gui.GuiTricks; + +public class CrashDialog { + + private static CrashDialog m_instance = null; + + private JFrame m_frame; + private JTextArea m_text; + + private CrashDialog(JFrame parent) { + // init frame + m_frame = new JFrame(Constants.NAME + " - Crash Report"); + final Container pane = m_frame.getContentPane(); + pane.setLayout(new BorderLayout()); + + JLabel label = new JLabel(Constants.NAME + " has crashed! =("); + label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + pane.add(label, BorderLayout.NORTH); + + // report panel + m_text = new JTextArea(); + m_text.setTabSize(2); + pane.add(new JScrollPane(m_text), BorderLayout.CENTER); + + // buttons panel + JPanel buttonsPanel = new JPanel(); + FlowLayout buttonsLayout = new FlowLayout(); + buttonsLayout.setAlignment(FlowLayout.RIGHT); + buttonsPanel.setLayout(buttonsLayout); + buttonsPanel.add(GuiTricks.unboldLabel(new JLabel("If you choose exit, you will lose any unsaved work."))); + JButton ignoreButton = new JButton("Ignore"); + ignoreButton.addActionListener(event -> { + // close (hide) the dialog + m_frame.setVisible(false); + }); + buttonsPanel.add(ignoreButton); + JButton exitButton = new JButton("Exit"); + exitButton.addActionListener(event -> { + // exit enigma + System.exit(1); + }); + buttonsPanel.add(exitButton); + pane.add(buttonsPanel, BorderLayout.SOUTH); + + // show the frame + m_frame.setSize(600, 400); + m_frame.setLocationRelativeTo(parent); + m_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + } + + public static void init(JFrame parent) { + m_instance = new CrashDialog(parent); + } + + public static void show(Throwable ex) { + // get the error report + StringWriter buf = new StringWriter(); + ex.printStackTrace(new PrintWriter(buf)); + String report = buf.toString(); + + // show it! + m_instance.m_text.setText(report); + m_instance.m_frame.doLayout(); + m_instance.m_frame.setVisible(true); + } +} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java new file mode 100644 index 0000000..dc4d91e --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.gui.dialog; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; + +import javax.swing.*; + +import cuchaz.enigma.Constants; +import cuchaz.enigma.Deobfuscator.ProgressListener; +import cuchaz.enigma.gui.GuiTricks; + +public class ProgressDialog implements ProgressListener, AutoCloseable { + + private JFrame frame; + private JLabel labelTitle; + private JLabel labelText; + private JProgressBar progress; + + public ProgressDialog(JFrame parent) { + + // init frame + this.frame = new JFrame(Constants.NAME + " - Operation in progress"); + final Container pane = this.frame.getContentPane(); + FlowLayout layout = new FlowLayout(); + layout.setAlignment(FlowLayout.LEFT); + pane.setLayout(layout); + + this.labelTitle = new JLabel(); + pane.add(this.labelTitle); + + // set up the progress bar + JPanel panel = new JPanel(); + pane.add(panel); + panel.setLayout(new BorderLayout()); + this.labelText = GuiTricks.unboldLabel(new JLabel()); + this.progress = new JProgressBar(); + this.labelText.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); + panel.add(this.labelText, BorderLayout.NORTH); + panel.add(this.progress, BorderLayout.CENTER); + panel.setPreferredSize(new Dimension(360, 50)); + + // show the frame + pane.doLayout(); + this.frame.setSize(400, 120); + this.frame.setResizable(false); + this.frame.setLocationRelativeTo(parent); + this.frame.setVisible(true); + this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + } + + public void close() { + this.frame.dispose(); + } + + @Override + public void init(int totalWork, String title) { + this.labelTitle.setText(title); + this.progress.setMinimum(0); + this.progress.setMaximum(totalWork); + this.progress.setValue(0); + } + + @Override + public void onProgress(int numDone, String message) { + this.labelText.setText(message); + this.progress.setValue(numDone); + + // update the frame + this.frame.validate(); + this.frame.repaint(); + } + + public interface ProgressRunnable { + void run(ProgressListener listener) throws Exception; + } + + public static void runInThread(final JFrame parent, final ProgressRunnable runnable) { + new Thread() { + @Override + public void run() { + try (ProgressDialog progress = new ProgressDialog(parent)) { + runnable.run(progress); + } catch (Exception ex) { + throw new Error(ex); + } + } + }.start(); + } +} diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java new file mode 100644 index 0000000..233d55e --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java @@ -0,0 +1,169 @@ +package cuchaz.enigma.gui.elements; + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.util.jar.JarFile; + +import javax.swing.*; + +import cuchaz.enigma.gui.Gui; +import cuchaz.enigma.gui.dialog.AboutDialog; +import cuchaz.enigma.mapping.MappingParseException; + +public class MenuBar extends JMenuBar { + + private final Gui gui; + + public final JMenuItem closeJarMenu; + + public final JMenuItem openMappingsMenu; + public final JMenuItem openOldMappingsMenu; + + public final JMenuItem saveMappingsMenu; + public final JMenuItem saveMappingsAsMenu; + public final JMenuItem closeMappingsMenu; + + + public final JMenuItem exportSourceMenu; + public final JMenuItem exportJarMenu; + + public MenuBar(Gui gui) { + this.gui = gui; + + { + JMenu menu = new JMenu("File"); + this.add(menu); + { + JMenuItem item = new JMenuItem("Open Jar..."); + menu.add(item); + item.addActionListener(event -> { + if (this.gui.jarFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + // load the jar in a separate thread + new Thread() { + @Override + public void run() { + try { + gui.getController().openJar(new JarFile(gui.jarFileChooser.getSelectedFile())); + } catch (IOException ex) { + throw new Error(ex); + } + } + }.start(); + } + }); + } + { + JMenuItem item = new JMenuItem("Close Jar"); + menu.add(item); + item.addActionListener(event -> this.gui.getController().closeJar()); + this.closeJarMenu = item; + } + menu.addSeparator(); + { + JMenuItem item = new JMenuItem("Open Mappings..."); + menu.add(item); + item.addActionListener(event -> { + if (this.gui.mappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + try { + this.gui.getController().openMappings(this.gui.mappingsFileChooser.getSelectedFile()); + } catch (IOException ex) { + throw new Error(ex); + } catch (MappingParseException ex) { + JOptionPane.showMessageDialog(this.gui.getFrame(), ex.getMessage()); + } + } + }); + this.openMappingsMenu = item; + } + { + JMenuItem item = new JMenuItem("Open Old Mappings..."); + menu.add(item); + item.addActionListener(event -> { + if (this.gui.oldMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + try { + this.gui.getController().openOldMappings(this.gui.oldMappingsFileChooser.getSelectedFile()); + } catch (IOException ex) { + throw new Error(ex); + } catch (MappingParseException ex) { + JOptionPane.showMessageDialog(this.gui.getFrame(), ex.getMessage()); + } + } + }); + this.openOldMappingsMenu = item; + } + menu.addSeparator(); + { + JMenuItem item = new JMenuItem("Save Mappings"); + menu.add(item); + item.addActionListener(event -> { + try { + this.gui.getController().saveMappings(this.gui.mappingsFileChooser.getSelectedFile()); + } catch (IOException ex) { + throw new Error(ex); + } + }); + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); + this.saveMappingsMenu = item; + } + { + JMenuItem item = new JMenuItem("Save Mappings As..."); + menu.add(item); + item.addActionListener(event -> { + if (this.gui.mappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + try { + this.gui.getController().saveMappings(this.gui.mappingsFileChooser.getSelectedFile()); + this.saveMappingsMenu.setEnabled(true); + } catch (IOException ex) { + throw new Error(ex); + } + } + }); + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); + this.saveMappingsAsMenu = item; + } + { + JMenuItem item = new JMenuItem("Close Mappings"); + menu.add(item); + item.addActionListener(event -> this.gui.getController().closeMappings()); + this.closeMappingsMenu = item; + } + menu.addSeparator(); + { + JMenuItem item = new JMenuItem("Export Source..."); + menu.add(item); + item.addActionListener(event -> { + if (this.gui.exportSourceFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + this.gui.getController().exportSource(this.gui.exportSourceFileChooser.getSelectedFile()); + } + }); + this.exportSourceMenu = item; + } + { + JMenuItem item = new JMenuItem("Export Jar..."); + menu.add(item); + item.addActionListener(event -> { + if (this.gui.exportJarFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { + this.gui.getController().exportJar(this.gui.exportJarFileChooser.getSelectedFile()); + } + }); + this.exportJarMenu = item; + } + menu.addSeparator(); + { + JMenuItem item = new JMenuItem("Exit"); + menu.add(item); + item.addActionListener(event -> this.gui.close()); + } + } + { + JMenu menu = new JMenu("Help"); + this.add(menu); + { + JMenuItem item = new JMenuItem("About"); + menu.add(item); + item.addActionListener(event -> AboutDialog.show(this.gui.getFrame())); + } + } + } +} diff --git a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java new file mode 100644 index 0000000..07c8a32 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java @@ -0,0 +1,82 @@ +package cuchaz.enigma.gui.elements; + +import java.awt.event.KeyEvent; + +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; + +import cuchaz.enigma.gui.Gui; + +public class PopupMenuBar extends JPopupMenu { + + private final Gui gui; + + public final JMenuItem renameMenu; + public final JMenuItem showInheritanceMenu; + public final JMenuItem showImplementationsMenu; + public final JMenuItem showCallsMenu; + public final JMenuItem openEntryMenu; + public final JMenuItem openPreviousMenu; + public final JMenuItem toggleMappingMenu; + + public PopupMenuBar(Gui gui) { + this.gui = gui; + { + JMenuItem menu = new JMenuItem("Rename"); + menu.addActionListener(event -> gui.startRename()); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0)); + menu.setEnabled(false); + this.add(menu); + this.renameMenu = menu; + } + { + JMenuItem menu = new JMenuItem("Show Inheritance"); + menu.addActionListener(event -> gui.showInheritance()); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 0)); + menu.setEnabled(false); + this.add(menu); + this.showInheritanceMenu = menu; + } + { + JMenuItem menu = new JMenuItem("Show Implementations"); + menu.addActionListener(event -> gui.showImplementations()); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, 0)); + menu.setEnabled(false); + this.add(menu); + this.showImplementationsMenu = menu; + } + { + JMenuItem menu = new JMenuItem("Show Calls"); + menu.addActionListener(event -> gui.showCalls()); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 0)); + menu.setEnabled(false); + this.add(menu); + this.showCallsMenu = menu; + } + { + JMenuItem menu = new JMenuItem("Go to Declaration"); + menu.addActionListener(event -> gui.navigateTo(gui.m_reference.entry)); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0)); + menu.setEnabled(false); + this.add(menu); + this.openEntryMenu = menu; + } + { + JMenuItem menu = new JMenuItem("Go to previous"); + menu.addActionListener(event -> gui.getController().openPreviousReference()); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0)); + menu.setEnabled(false); + this.add(menu); + this.openPreviousMenu = menu; + } + { + JMenuItem menu = new JMenuItem("Mark as deobfuscated"); + menu.addActionListener(event -> gui.toggleMapping()); + menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0)); + menu.setEnabled(false); + this.add(menu); + this.toggleMappingMenu = menu; + } + } +} diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java new file mode 100644 index 0000000..62a0f20 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java @@ -0,0 +1,8 @@ +package cuchaz.enigma.gui.filechooser; + +import javax.swing.JFileChooser; + +public class FileChooserFile extends JFileChooser { + public FileChooserFile() { + } +} diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java new file mode 100644 index 0000000..bd8f0f0 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java @@ -0,0 +1,11 @@ +package cuchaz.enigma.gui.filechooser; + +import javax.swing.JFileChooser; + +public class FileChooserFolder extends JFileChooser{ + + public FileChooserFolder() { + this.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + this.setAcceptAllFileFilterUsed(false); + } +} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java b/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java new file mode 100644 index 0000000..d89de36 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java @@ -0,0 +1,28 @@ +package cuchaz.enigma.gui.panels; + +import java.awt.BorderLayout; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import cuchaz.enigma.gui.ClassSelector; +import cuchaz.enigma.gui.Gui; + +public class PanelDeobf extends JPanel { + + public final ClassSelector deobfClasses; + private final Gui gui; + + public PanelDeobf(Gui gui) { + this.gui = gui; + + this.deobfClasses = new ClassSelector(ClassSelector.DeobfuscatedClassEntryComparator); + this.deobfClasses.setListener(gui::navigateTo); + + this.setLayout(new BorderLayout()); + this.add(new JLabel("De-obfuscated Classes"), BorderLayout.NORTH); + this.add(new JScrollPane(this.deobfClasses), BorderLayout.CENTER); + + } +} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java new file mode 100644 index 0000000..6237710 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java @@ -0,0 +1,60 @@ +package cuchaz.enigma.gui.panels; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.JEditorPane; + +import cuchaz.enigma.gui.BrowserCaret; +import cuchaz.enigma.gui.Gui; +import de.sciss.syntaxpane.DefaultSyntaxKit; + +public class PanelEditor extends JEditorPane { + private final Gui gui; + + public PanelEditor(Gui gui) { + this.gui = gui; + + this.setEditable(false); + this.setCaret(new BrowserCaret()); + this.setContentType("text/java"); + this.addCaretListener(event -> gui.onCaretMove(event.getDot())); + this.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent event) { + switch (event.getKeyCode()) { + case KeyEvent.VK_R: + gui.popupMenu.renameMenu.doClick(); + break; + + case KeyEvent.VK_I: + gui.popupMenu.showInheritanceMenu.doClick(); + break; + + case KeyEvent.VK_M: + gui.popupMenu.showImplementationsMenu.doClick(); + break; + + case KeyEvent.VK_N: + gui.popupMenu.openEntryMenu.doClick(); + break; + + case KeyEvent.VK_P: + gui.popupMenu.openPreviousMenu.doClick(); + break; + + case KeyEvent.VK_C: + gui.popupMenu.showCallsMenu.doClick(); + break; + + case KeyEvent.VK_T: + gui.popupMenu.toggleMappingMenu.doClick(); + break; + } + } + }); + + DefaultSyntaxKit kit = (DefaultSyntaxKit) this.getEditorKit(); + kit.toggleComponent(this, "de.sciss.syntaxpane.components.TokenMarker"); + } +} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java b/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java new file mode 100644 index 0000000..4261eb5 --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java @@ -0,0 +1,34 @@ +package cuchaz.enigma.gui.panels; + +import java.awt.Dimension; +import java.awt.GridLayout; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import cuchaz.enigma.gui.Gui; +import cuchaz.enigma.gui.GuiTricks; + +public class PanelIdentifier extends JPanel { + + private final Gui gui; + + public PanelIdentifier(Gui gui) { + this.gui = gui; + + this.setLayout(new GridLayout(4, 1, 0, 0)); + this.setPreferredSize(new Dimension(0, 100)); + this.setBorder(BorderFactory.createTitledBorder("Identifier Info")); + } + + public void clearReference() { + this.removeAll(); + JLabel label = new JLabel("No identifier selected"); + GuiTricks.unboldLabel(label); + label.setHorizontalAlignment(JLabel.CENTER); + this.add(label); + + gui.redraw(); + } +} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java b/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java new file mode 100644 index 0000000..745cb2e --- /dev/null +++ b/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java @@ -0,0 +1,27 @@ +package cuchaz.enigma.gui.panels; + +import java.awt.BorderLayout; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import cuchaz.enigma.gui.ClassSelector; +import cuchaz.enigma.gui.Gui; + +public class PanelObf extends JPanel { + + private final Gui gui; + public final ClassSelector obfClasses; + + public PanelObf(Gui gui) { + this.gui = gui; + + this.obfClasses = new ClassSelector(ClassSelector.ObfuscatedClassEntryComparator); + this.obfClasses.setListener(gui::navigateTo); + + this.setLayout(new BorderLayout()); + this.add(new JLabel("Obfuscated Classes"), BorderLayout.NORTH); + this.add(new JScrollPane(this.obfClasses), BorderLayout.CENTER); + } +} -- cgit v1.2.3