From 0f47403d0220757fed189b76e2071e25b1025cb8 Mon Sep 17 00:00:00 2001 From: Runemoro Date: Wed, 3 Jun 2020 13:39:42 -0400 Subject: Split GUI code to separate module (#242) * Split into modules * Post merge compile fixes Co-authored-by: modmuss50 --- src/main/java/cuchaz/enigma/gui/BrowserCaret.java | 28 - src/main/java/cuchaz/enigma/gui/ClassSelector.java | 532 ---------- src/main/java/cuchaz/enigma/gui/CodeReader.java | 73 -- .../java/cuchaz/enigma/gui/ConnectionState.java | 7 - .../cuchaz/enigma/gui/DecompiledClassSource.java | 159 --- .../cuchaz/enigma/gui/EnigmaQuickFindDialog.java | 90 -- .../java/cuchaz/enigma/gui/EnigmaSyntaxKit.java | 44 - src/main/java/cuchaz/enigma/gui/Gui.java | 1058 -------------------- src/main/java/cuchaz/enigma/gui/GuiController.java | 729 -------------- .../cuchaz/enigma/gui/MessageListCellRenderer.java | 24 - .../cuchaz/enigma/gui/MethodTreeCellRenderer.java | 42 - .../java/cuchaz/enigma/gui/QuickFindAction.java | 45 - src/main/java/cuchaz/enigma/gui/RefreshMode.java | 7 - .../java/cuchaz/enigma/gui/SourceRemapper.java | 64 -- .../cuchaz/enigma/gui/TokenListCellRenderer.java | 35 - .../java/cuchaz/enigma/gui/dialog/AboutDialog.java | 69 -- .../cuchaz/enigma/gui/dialog/ChangeDialog.java | 50 - .../enigma/gui/dialog/ConnectToServerDialog.java | 82 -- .../java/cuchaz/enigma/gui/dialog/CrashDialog.java | 105 -- .../enigma/gui/dialog/CreateServerDialog.java | 65 -- .../cuchaz/enigma/gui/dialog/JavadocDialog.java | 159 --- .../cuchaz/enigma/gui/dialog/ProgressDialog.java | 109 -- .../cuchaz/enigma/gui/dialog/SearchDialog.java | 261 ----- .../java/cuchaz/enigma/gui/dialog/StatsDialog.java | 82 -- .../enigma/gui/elements/CollapsibleTabbedPane.java | 40 - .../java/cuchaz/enigma/gui/elements/MenuBar.java | 386 ------- .../cuchaz/enigma/gui/elements/PopupMenuBar.java | 125 --- .../enigma/gui/filechooser/FileChooserAny.java | 10 - .../enigma/gui/filechooser/FileChooserFile.java | 8 - .../enigma/gui/filechooser/FileChooserFolder.java | 11 - .../enigma/gui/highlight/BoxHighlightPainter.java | 69 -- .../gui/highlight/SelectionHighlightPainter.java | 31 - .../enigma/gui/highlight/TokenHighlightType.java | 7 - .../enigma/gui/node/ClassSelectorClassNode.java | 72 -- .../enigma/gui/node/ClassSelectorPackageNode.java | 58 -- .../java/cuchaz/enigma/gui/panels/PanelDeobf.java | 26 - .../java/cuchaz/enigma/gui/panels/PanelEditor.java | 171 ---- .../cuchaz/enigma/gui/panels/PanelIdentifier.java | 32 - .../java/cuchaz/enigma/gui/panels/PanelObf.java | 37 - .../cuchaz/enigma/gui/stats/StatsGenerator.java | 197 ---- .../java/cuchaz/enigma/gui/stats/StatsMember.java | 8 - .../enigma/gui/util/AbstractListCellRenderer.java | 77 -- src/main/java/cuchaz/enigma/gui/util/History.java | 49 - .../enigma/gui/util/ScaleChangeListener.java | 8 - .../java/cuchaz/enigma/gui/util/ScaleUtil.java | 110 -- 45 files changed, 5451 deletions(-) delete mode 100644 src/main/java/cuchaz/enigma/gui/BrowserCaret.java delete mode 100644 src/main/java/cuchaz/enigma/gui/ClassSelector.java delete mode 100644 src/main/java/cuchaz/enigma/gui/CodeReader.java delete mode 100644 src/main/java/cuchaz/enigma/gui/ConnectionState.java delete mode 100644 src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java delete mode 100644 src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java delete mode 100644 src/main/java/cuchaz/enigma/gui/Gui.java delete mode 100644 src/main/java/cuchaz/enigma/gui/GuiController.java delete mode 100644 src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/QuickFindAction.java delete mode 100644 src/main/java/cuchaz/enigma/gui/RefreshMode.java delete mode 100644 src/main/java/cuchaz/enigma/gui/SourceRemapper.java delete mode 100644 src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java delete mode 100644 src/main/java/cuchaz/enigma/gui/elements/MenuBar.java delete mode 100644 src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java delete mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java delete mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java delete mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java delete mode 100644 src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java delete mode 100644 src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java delete mode 100644 src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java delete mode 100644 src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java delete mode 100644 src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelObf.java delete mode 100644 src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java delete mode 100644 src/main/java/cuchaz/enigma/gui/stats/StatsMember.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/History.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java (limited to 'src/main/java/cuchaz/enigma/gui') diff --git a/src/main/java/cuchaz/enigma/gui/BrowserCaret.java b/src/main/java/cuchaz/enigma/gui/BrowserCaret.java deleted file mode 100644 index af105db..0000000 --- a/src/main/java/cuchaz/enigma/gui/BrowserCaret.java +++ /dev/null @@ -1,28 +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 javax.swing.text.DefaultCaret; - -public class BrowserCaret extends DefaultCaret { - - @Override - public boolean isSelectionVisible() { - return true; - } - - @Override - public boolean isVisible() { - return true; - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/ClassSelector.java b/src/main/java/cuchaz/enigma/gui/ClassSelector.java deleted file mode 100644 index a23e24c..0000000 --- a/src/main/java/cuchaz/enigma/gui/ClassSelector.java +++ /dev/null @@ -1,532 +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.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.*; - -import javax.annotation.Nullable; -import javax.swing.JOptionPane; -import javax.swing.JTree; -import javax.swing.event.CellEditorListener; -import javax.swing.event.ChangeEvent; -import javax.swing.tree.*; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import cuchaz.enigma.gui.node.ClassSelectorClassNode; -import cuchaz.enigma.gui.node.ClassSelectorPackageNode; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -public class ClassSelector extends JTree { - - public static final Comparator DEOBF_CLASS_COMPARATOR = Comparator.comparing(ClassEntry::getFullName); - - private final GuiController controller; - - private DefaultMutableTreeNode rootNodes; - private ClassSelectionListener selectionListener; - private RenameSelectionListener renameSelectionListener; - private Comparator comparator; - - private final Map displayedObfToDeobf = new HashMap<>(); - - public ClassSelector(Gui gui, Comparator comparator, boolean isRenamable) { - this.comparator = comparator; - this.controller = gui.getController(); - - // configure the tree control - setEditable(true); - setRootVisible(false); - setShowsRootHandles(false); - setModel(null); - - // hook events - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (selectionListener != null && event.getClickCount() == 2) { - // get the selected node - TreePath path = getSelectionPath(); - if (path != null && path.getLastPathComponent() instanceof ClassSelectorClassNode) { - ClassSelectorClassNode node = (ClassSelectorClassNode) path.getLastPathComponent(); - selectionListener.onSelectClass(node.getObfEntry()); - } - } - } - }); - - final JTree tree = this; - - final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, - (DefaultTreeCellRenderer) tree.getCellRenderer()) { - @Override - public boolean isCellEditable(EventObject event) { - return isRenamable && !(event instanceof MouseEvent) && super.isCellEditable(event); - } - }; - this.setCellEditor(editor); - editor.addCellEditorListener(new CellEditorListener() { - @Override - public void editingStopped(ChangeEvent e) { - String data = editor.getCellEditorValue().toString(); - TreePath path = getSelectionPath(); - - Object realPath = path.getLastPathComponent(); - if (realPath != null && realPath instanceof DefaultMutableTreeNode && data != null) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) realPath; - TreeNode parentNode = node.getParent(); - if (parentNode == null) - return; - boolean allowEdit = true; - for (int i = 0; i < parentNode.getChildCount(); i++) { - TreeNode childNode = parentNode.getChildAt(i); - if (childNode != null && childNode.toString().equals(data) && childNode != node) { - allowEdit = false; - break; - } - } - if (allowEdit && renameSelectionListener != null) { - Object prevData = node.getUserObject(); - Object objectData = node.getUserObject() instanceof ClassEntry ? new ClassEntry(((ClassEntry) prevData).getPackageName() + "/" + data) : data; - try { - renameSelectionListener.onSelectionRename(node.getUserObject(), objectData, node); - node.setUserObject(objectData); // Make sure that it's modified - } catch (IllegalNameException ex) { - JOptionPane.showOptionDialog(gui.getFrame(), ex.getMessage(), "Enigma - Error", JOptionPane.OK_OPTION, - JOptionPane.ERROR_MESSAGE, null, new String[]{"Ok"}, "OK"); - editor.cancelCellEditing(); - } - } else - editor.cancelCellEditing(); - } - - } - - @Override - public void editingCanceled(ChangeEvent e) { - // NOP - } - }); - // init defaults - this.selectionListener = null; - this.renameSelectionListener = null; - } - - public boolean isDuplicate(Object[] nodes, String data) { - int count = 0; - - for (Object node : nodes) { - if (node.toString().equals(data)) { - count++; - if (count == 2) - return true; - } - } - return false; - } - - public void setSelectionListener(ClassSelectionListener val) { - this.selectionListener = val; - } - - public void setRenameSelectionListener(RenameSelectionListener renameSelectionListener) { - this.renameSelectionListener = renameSelectionListener; - } - - public void setClasses(Collection classEntries) { - displayedObfToDeobf.clear(); - - List state = getExpansionState(this); - if (classEntries == null) { - setModel(null); - return; - } - - Translator translator = controller.project.getMapper().getDeobfuscator(); - - // build the package names - Map packages = Maps.newHashMap(); - for (ClassEntry obfClass : classEntries) { - ClassEntry deobfClass = translator.translate(obfClass); - packages.put(deobfClass.getPackageName(), null); - } - - // sort the packages - List sortedPackageNames = Lists.newArrayList(packages.keySet()); - sortedPackageNames.sort((a, b) -> - { - // I can never keep this rule straight when writing these damn things... - // a < b => -1, a == b => 0, a > b => +1 - - if (b == null || a == null) { - return 0; - } - - String[] aparts = a.split("/"); - String[] bparts = b.split("/"); - for (int i = 0; true; i++) { - if (i >= aparts.length) { - return -1; - } else if (i >= bparts.length) { - return 1; - } - - int result = aparts[i].compareTo(bparts[i]); - if (result != 0) { - return result; - } - } - }); - - // create the rootNodes node and the package nodes - rootNodes = new DefaultMutableTreeNode(); - for (String packageName : sortedPackageNames) { - ClassSelectorPackageNode node = new ClassSelectorPackageNode(packageName); - packages.put(packageName, node); - rootNodes.add(node); - } - - // put the classes into packages - Multimap packagedClassEntries = ArrayListMultimap.create(); - for (ClassEntry obfClass : classEntries) { - ClassEntry deobfClass = translator.translate(obfClass); - packagedClassEntries.put(deobfClass.getPackageName(), obfClass); - } - - // build the class nodes - for (String packageName : packagedClassEntries.keySet()) { - // sort the class entries - List classEntriesInPackage = Lists.newArrayList(packagedClassEntries.get(packageName)); - classEntriesInPackage.sort((o1, o2) -> comparator.compare(translator.translate(o1), translator.translate(o2))); - - // create the nodes in order - for (ClassEntry obfClass : classEntriesInPackage) { - ClassEntry deobfClass = translator.translate(obfClass); - ClassSelectorPackageNode node = packages.get(packageName); - ClassSelectorClassNode classNode = new ClassSelectorClassNode(obfClass, deobfClass); - displayedObfToDeobf.put(obfClass, deobfClass); - node.add(classNode); - } - } - - // finally, update the tree control - setModel(new DefaultTreeModel(rootNodes)); - - restoreExpansionState(this, state); - } - - public ClassEntry getSelectedClass() { - if (!isSelectionEmpty()) { - Object selectedNode = getSelectionPath().getLastPathComponent(); - if (selectedNode instanceof ClassSelectorClassNode) { - ClassSelectorClassNode classNode = (ClassSelectorClassNode) selectedNode; - return classNode.getClassEntry(); - } - } - return null; - } - - public String getSelectedPackage() { - if (!isSelectionEmpty()) { - Object selectedNode = getSelectionPath().getLastPathComponent(); - if (selectedNode instanceof ClassSelectorPackageNode) { - ClassSelectorPackageNode packageNode = (ClassSelectorPackageNode) selectedNode; - return packageNode.getPackageName(); - } else if (selectedNode instanceof ClassSelectorClassNode) { - ClassSelectorClassNode classNode = (ClassSelectorClassNode) selectedNode; - return classNode.getClassEntry().getPackageName(); - } - } - return null; - } - - public boolean isDescendant(TreePath path1, TreePath path2) { - int count1 = path1.getPathCount(); - int count2 = path2.getPathCount(); - if (count1 <= count2) { - return false; - } - while (count1 != count2) { - path1 = path1.getParentPath(); - count1--; - } - return path1.equals(path2); - } - - public enum State { - EXPANDED, - SELECTED - } - - public static class StateEntry { - public final State state; - public final TreePath path; - - public StateEntry(State state, TreePath path) { - this.state = state; - this.path = path; - } - } - - public List getExpansionState(JTree tree) { - List state = new ArrayList<>(); - int rowCount = tree.getRowCount(); - for (int i = 0; i < rowCount; i++) { - TreePath path = tree.getPathForRow(i); - if (tree.isPathSelected(path)) { - state.add(new StateEntry(State.SELECTED, path)); - } - if (tree.isExpanded(path)) { - state.add(new StateEntry(State.EXPANDED, path)); - } - } - return state; - } - - public void restoreExpansionState(JTree tree, List expansionState) { - tree.clearSelection(); - - for (StateEntry entry : expansionState) { - switch (entry.state) { - case SELECTED: - tree.addSelectionPath(entry.path); - break; - case EXPANDED: - tree.expandPath(entry.path); - break; - } - } - } - - public List packageNodes() { - List nodes = Lists.newArrayList(); - DefaultMutableTreeNode root = (DefaultMutableTreeNode) getModel().getRoot(); - Enumeration children = root.children(); - while (children.hasMoreElements()) { - ClassSelectorPackageNode packageNode = (ClassSelectorPackageNode) children.nextElement(); - nodes.add(packageNode); - } - return nodes; - } - - public List classNodes(ClassSelectorPackageNode packageNode) { - List nodes = Lists.newArrayList(); - Enumeration children = packageNode.children(); - while (children.hasMoreElements()) { - ClassSelectorClassNode classNode = (ClassSelectorClassNode) children.nextElement(); - nodes.add(classNode); - } - return nodes; - } - - public void expandPackage(String packageName) { - if (packageName == null) { - return; - } - for (ClassSelectorPackageNode packageNode : packageNodes()) { - if (packageNode.getPackageName().equals(packageName)) { - expandPath(new TreePath(new Object[]{getModel().getRoot(), packageNode})); - return; - } - } - } - - public void expandAll() { - for (ClassSelectorPackageNode packageNode : packageNodes()) { - expandPath(new TreePath(new Object[]{getModel().getRoot(), packageNode})); - } - } - - public ClassEntry getFirstClass() { - ClassSelectorPackageNode packageNode = packageNodes().get(0); - if (packageNode != null) { - ClassSelectorClassNode classNode = classNodes(packageNode).get(0); - if (classNode != null) { - return classNode.getClassEntry(); - } - } - return null; - } - - public ClassSelectorPackageNode getPackageNode(ClassEntry entry) { - String packageName = entry.getPackageName(); - if (packageName == null) { - packageName = "(none)"; - } - for (ClassSelectorPackageNode packageNode : packageNodes()) { - if (packageNode.getPackageName().equals(packageName)) { - return packageNode; - } - } - return null; - } - - @Nullable - public ClassEntry getDisplayedDeobf(ClassEntry obfEntry) { - return displayedObfToDeobf.get(obfEntry); - } - - public ClassSelectorPackageNode getPackageNode(ClassSelector selector, ClassEntry entry) { - ClassSelectorPackageNode packageNode = getPackageNode(entry); - - if (selector != null && packageNode == null && selector.getPackageNode(entry) != null) - return selector.getPackageNode(entry); - return packageNode; - } - - public ClassEntry getNextClass(ClassEntry entry) { - boolean foundIt = false; - for (ClassSelectorPackageNode packageNode : packageNodes()) { - if (!foundIt) { - // skip to the package with our target in it - if (packageNode.getPackageName().equals(entry.getPackageName())) { - for (ClassSelectorClassNode classNode : classNodes(packageNode)) { - if (!foundIt) { - if (classNode.getClassEntry().equals(entry)) { - foundIt = true; - } - } else { - // return the next class - return classNode.getClassEntry(); - } - } - } - } else { - // return the next class - ClassSelectorClassNode classNode = classNodes(packageNode).get(0); - if (classNode != null) { - return classNode.getClassEntry(); - } - } - } - return null; - } - - public void setSelectionClass(ClassEntry classEntry) { - expandPackage(classEntry.getPackageName()); - for (ClassSelectorPackageNode packageNode : packageNodes()) { - for (ClassSelectorClassNode classNode : classNodes(packageNode)) { - if (classNode.getClassEntry().equals(classEntry)) { - TreePath path = new TreePath(new Object[]{getModel().getRoot(), packageNode, classNode}); - setSelectionPath(path); - scrollPathToVisible(path); - } - } - } - } - - public void removeNode(ClassSelectorPackageNode packageNode, ClassEntry entry) { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - - if (packageNode == null) - return; - - for (int i = 0; i < packageNode.getChildCount(); i++) { - DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) packageNode.getChildAt(i); - if (childNode.getUserObject() instanceof ClassEntry && childNode.getUserObject().equals(entry)) { - model.removeNodeFromParent(childNode); - if (childNode instanceof ClassSelectorClassNode) { - displayedObfToDeobf.remove(((ClassSelectorClassNode) childNode).getObfEntry()); - } - break; - } - } - } - - public void removeNodeIfEmpty(ClassSelectorPackageNode packageNode) { - if (packageNode != null && packageNode.getChildCount() == 0) - ((DefaultTreeModel) getModel()).removeNodeFromParent(packageNode); - } - - public void moveClassIn(ClassEntry classEntry) { - removeEntry(classEntry); - insertNode(classEntry); - } - - public void moveClassOut(ClassEntry classEntry) { - removeEntry(classEntry); - } - - private void removeEntry(ClassEntry classEntry) { - ClassEntry previousDeobf = displayedObfToDeobf.get(classEntry); - if (previousDeobf != null) { - ClassSelectorPackageNode packageNode = getPackageNode(previousDeobf); - removeNode(packageNode, previousDeobf); - removeNodeIfEmpty(packageNode); - } - } - - public ClassSelectorPackageNode getOrCreatePackage(ClassEntry entry) { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - ClassSelectorPackageNode newPackageNode = getPackageNode(entry); - if (newPackageNode == null) { - newPackageNode = new ClassSelectorPackageNode(entry.getPackageName()); - model.insertNodeInto(newPackageNode, (MutableTreeNode) model.getRoot(), getPlacementIndex(newPackageNode)); - } - return newPackageNode; - } - - public void insertNode(ClassEntry obfEntry) { - ClassEntry deobfEntry = controller.project.getMapper().deobfuscate(obfEntry); - ClassSelectorPackageNode packageNode = getOrCreatePackage(deobfEntry); - - DefaultTreeModel model = (DefaultTreeModel) getModel(); - ClassSelectorClassNode classNode = new ClassSelectorClassNode(obfEntry, deobfEntry); - model.insertNodeInto(classNode, packageNode, getPlacementIndex(packageNode, classNode)); - - displayedObfToDeobf.put(obfEntry, deobfEntry); - } - - public void reload() { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - model.reload(rootNodes); - } - - private int getPlacementIndex(ClassSelectorPackageNode newPackageNode, ClassSelectorClassNode classNode) { - List classNodes = classNodes(newPackageNode); - classNodes.add(classNode); - classNodes.sort((a, b) -> comparator.compare(a.getClassEntry(), b.getClassEntry())); - for (int i = 0; i < classNodes.size(); i++) - if (classNodes.get(i) == classNode) - return i; - - return 0; - } - - private int getPlacementIndex(ClassSelectorPackageNode newPackageNode) { - List packageNodes = packageNodes(); - if (!packageNodes.contains(newPackageNode)) { - packageNodes.add(newPackageNode); - packageNodes.sort(Comparator.comparing(ClassSelectorPackageNode::toString)); - } - - for (int i = 0; i < packageNodes.size(); i++) - if (packageNodes.get(i) == newPackageNode) - return i; - - return 0; - } - - public interface ClassSelectionListener { - void onSelectClass(ClassEntry classEntry); - } - - public interface RenameSelectionListener { - void onSelectionRename(Object prevData, Object data, DefaultMutableTreeNode node); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/CodeReader.java b/src/main/java/cuchaz/enigma/gui/CodeReader.java deleted file mode 100644 index e119640..0000000 --- a/src/main/java/cuchaz/enigma/gui/CodeReader.java +++ /dev/null @@ -1,73 +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 cuchaz.enigma.analysis.Token; - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.Highlighter.HighlightPainter; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class CodeReader extends JEditorPane { - private static final long serialVersionUID = 3673180950485748810L; - - // HACKHACK: someday we can update the main GUI to use this code reader - public static void navigateToToken(final JEditorPane editor, final Token token, final HighlightPainter highlightPainter) { - - // set the caret position to the token - Document document = editor.getDocument(); - int clampedPosition = Math.min(Math.max(token.start, 0), document.getLength()); - - editor.setCaretPosition(clampedPosition); - editor.grabFocus(); - - try { - // make sure the token is visible in the scroll window - Rectangle start = editor.modelToView(token.start); - Rectangle end = editor.modelToView(token.end); - final Rectangle show = start.union(end); - show.grow(start.width * 10, start.height * 6); - SwingUtilities.invokeLater(() -> editor.scrollRectToVisible(show)); - } catch (BadLocationException ex) { - throw new Error(ex); - } - - // highlight the token momentarily - final Timer timer = new Timer(200, new ActionListener() { - private int counter = 0; - private Object highlight = null; - - @Override - public void actionPerformed(ActionEvent event) { - if (counter % 2 == 0) { - try { - highlight = editor.getHighlighter().addHighlight(token.start, token.end, highlightPainter); - } catch (BadLocationException ex) { - // don't care - } - } else if (highlight != null) { - editor.getHighlighter().removeHighlight(highlight); - } - - if (counter++ > 6) { - Timer timer = (Timer) event.getSource(); - timer.stop(); - } - } - }); - timer.start(); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/ConnectionState.java b/src/main/java/cuchaz/enigma/gui/ConnectionState.java deleted file mode 100644 index db6590d..0000000 --- a/src/main/java/cuchaz/enigma/gui/ConnectionState.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.gui; - -public enum ConnectionState { - NOT_CONNECTED, - HOSTING, - CONNECTED, -} diff --git a/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java b/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java deleted file mode 100644 index 08df3e7..0000000 --- a/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java +++ /dev/null @@ -1,159 +0,0 @@ -package cuchaz.enigma.gui; - -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.EnigmaServices; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.gui.highlight.TokenHighlightType; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.translation.LocalNameGenerator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.LocalVariableDefEntry; - -import javax.annotation.Nullable; -import java.util.*; - -public class DecompiledClassSource { - private final ClassEntry classEntry; - - private final SourceIndex obfuscatedIndex; - private SourceIndex remappedIndex; - - private final Map> highlightedTokens = new EnumMap<>(TokenHighlightType.class); - - public DecompiledClassSource(ClassEntry classEntry, SourceIndex index) { - this.classEntry = classEntry; - this.obfuscatedIndex = index; - this.remappedIndex = index; - } - - public static DecompiledClassSource text(ClassEntry classEntry, String text) { - return new DecompiledClassSource(classEntry, new SourceIndex(text)); - } - - public void remapSource(EnigmaProject project, Translator translator) { - highlightedTokens.clear(); - - SourceRemapper remapper = new SourceRemapper(obfuscatedIndex.getSource(), obfuscatedIndex.referenceTokens()); - - SourceRemapper.Result remapResult = remapper.remap((token, movedToken) -> remapToken(project, token, movedToken, translator)); - remappedIndex = obfuscatedIndex.remapTo(remapResult); - } - - private String remapToken(EnigmaProject project, Token token, Token movedToken, Translator translator) { - EntryReference, Entry> reference = obfuscatedIndex.getReference(token); - - Entry entry = reference.getNameableEntry(); - Entry translatedEntry = translator.translate(entry); - - if (project.isRenamable(reference)) { - if (isDeobfuscated(entry, translatedEntry)) { - highlightToken(movedToken, TokenHighlightType.DEOBFUSCATED); - return translatedEntry.getSourceRemapName(); - } else { - Optional proposedName = proposeName(project, entry); - if (proposedName.isPresent()) { - highlightToken(movedToken, TokenHighlightType.PROPOSED); - return proposedName.get(); - } - - highlightToken(movedToken, TokenHighlightType.OBFUSCATED); - } - } - - String defaultName = generateDefaultName(translatedEntry); - if (defaultName != null) { - return defaultName; - } - - return null; - } - - private Optional proposeName(EnigmaProject project, Entry entry) { - EnigmaServices services = project.getEnigma().getServices(); - - return services.get(NameProposalService.TYPE).stream().flatMap(nameProposalService -> { - EntryRemapper mapper = project.getMapper(); - Collection> resolved = mapper.getObfResolver().resolveEntry(entry, ResolutionStrategy.RESOLVE_ROOT); - - return resolved.stream() - .map(e -> nameProposalService.proposeName(e, mapper)) - .filter(Optional::isPresent) - .map(Optional::get); - }).findFirst(); - } - - @Nullable - private String generateDefaultName(Entry entry) { - if (entry instanceof LocalVariableDefEntry) { - LocalVariableDefEntry localVariable = (LocalVariableDefEntry) entry; - - int index = localVariable.getIndex(); - if (localVariable.isArgument()) { - List arguments = localVariable.getParent().getDesc().getArgumentDescs(); - return LocalNameGenerator.generateArgumentName(index, localVariable.getDesc(), arguments); - } else { - return LocalNameGenerator.generateLocalVariableName(index, localVariable.getDesc()); - } - } - - return null; - } - - private boolean isDeobfuscated(Entry entry, Entry translatedEntry) { - return !entry.getName().equals(translatedEntry.getName()); - } - - public ClassEntry getEntry() { - return classEntry; - } - - public SourceIndex getIndex() { - return remappedIndex; - } - - public Map> getHighlightedTokens() { - return highlightedTokens; - } - - private void highlightToken(Token token, TokenHighlightType highlightType) { - highlightedTokens.computeIfAbsent(highlightType, t -> new ArrayList<>()).add(token); - } - - public int getObfuscatedOffset(int deobfOffset) { - return getOffset(remappedIndex, obfuscatedIndex, deobfOffset); - } - - public int getDeobfuscatedOffset(int obfOffset) { - return getOffset(obfuscatedIndex, remappedIndex, obfOffset); - } - - private static int getOffset(SourceIndex fromIndex, SourceIndex toIndex, int fromOffset) { - int relativeOffset = 0; - - Iterator fromTokenItr = fromIndex.referenceTokens().iterator(); - Iterator toTokenItr = toIndex.referenceTokens().iterator(); - while (fromTokenItr.hasNext() && toTokenItr.hasNext()) { - Token fromToken = fromTokenItr.next(); - Token toToken = toTokenItr.next(); - if (fromToken.end > fromOffset) { - break; - } - - relativeOffset = toToken.end - fromToken.end; - } - - return fromOffset + relativeOffset; - } - - @Override - public String toString() { - return remappedIndex.getSource(); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java b/src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java deleted file mode 100644 index c912be3..0000000 --- a/src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java +++ /dev/null @@ -1,90 +0,0 @@ -package cuchaz.enigma.gui; - -import de.sciss.syntaxpane.actions.DocumentSearchData; -import de.sciss.syntaxpane.actions.gui.QuickFindDialog; - -import javax.swing.*; -import javax.swing.text.JTextComponent; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -public class EnigmaQuickFindDialog extends QuickFindDialog { - public EnigmaQuickFindDialog(JTextComponent target) { - super(target, DocumentSearchData.getFromEditor(target)); - - JToolBar toolBar = getToolBar(); - JTextField textField = getTextField(toolBar); - - textField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - super.keyPressed(e); - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - JToolBar toolBar = getToolBar(); - boolean next = !e.isShiftDown(); - JButton button = next ? getNextButton(toolBar) : getPrevButton(toolBar); - button.doClick(); - } - } - }); - } - - @Override - public void showFor(JTextComponent target) { - String selectedText = target.getSelectedText(); - - try { - super.showFor(target); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - Container view = target.getParent(); - Point loc = new Point(0, view.getHeight() - getSize().height); - setLocationRelativeTo(view); - SwingUtilities.convertPointToScreen(loc, view); - setLocation(loc); - - JToolBar toolBar = getToolBar(); - JTextField textField = getTextField(toolBar); - - if (selectedText != null) { - textField.setText(selectedText); - } - - textField.selectAll(); - } - - private JToolBar getToolBar() { - return components(getContentPane(), JToolBar.class).findFirst().orElse(null); - } - - private JTextField getTextField(JToolBar toolBar) { - return components(toolBar, JTextField.class).findFirst().orElse(null); - } - - private JButton getNextButton(JToolBar toolBar) { - Stream buttons = components(toolBar, JButton.class); - return buttons.skip(1).findFirst().orElse(null); - } - - private JButton getPrevButton(JToolBar toolBar) { - Stream buttons = components(toolBar, JButton.class); - return buttons.findFirst().orElse(null); - } - - private static Stream components(Container container) { - return IntStream.range(0, container.getComponentCount()) - .mapToObj(container::getComponent); - } - - private static Stream components(Container container, Class type) { - return components(container) - .filter(type::isInstance) - .map(type::cast); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java b/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java deleted file mode 100644 index 42eaa60..0000000 --- a/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java +++ /dev/null @@ -1,44 +0,0 @@ -package cuchaz.enigma.gui; - -import cuchaz.enigma.config.Config; -import de.sciss.syntaxpane.components.LineNumbersRuler; -import de.sciss.syntaxpane.syntaxkits.JavaSyntaxKit; -import de.sciss.syntaxpane.util.Configuration; - -public class EnigmaSyntaxKit extends JavaSyntaxKit { - private static Configuration configuration = null; - - @Override - public Configuration getConfig() { - if(configuration == null){ - initConfig(super.getConfig(JavaSyntaxKit.class)); - } - return configuration; - } - - public void initConfig(Configuration baseConfig){ - configuration = baseConfig; - //See de.sciss.syntaxpane.TokenType - configuration.put("Style.KEYWORD", Config.getInstance().highlightColor + ", 0"); - configuration.put("Style.KEYWORD2", Config.getInstance().highlightColor + ", 3"); - configuration.put("Style.STRING", Config.getInstance().stringColor + ", 0"); - configuration.put("Style.STRING2", Config.getInstance().stringColor + ", 1"); - configuration.put("Style.NUMBER", Config.getInstance().numberColor + ", 1"); - configuration.put("Style.OPERATOR", Config.getInstance().operatorColor + ", 0"); - configuration.put("Style.DELIMITER", Config.getInstance().delimiterColor + ", 1"); - configuration.put("Style.TYPE", Config.getInstance().typeColor + ", 2"); - configuration.put("Style.TYPE2", Config.getInstance().typeColor + ", 1"); - configuration.put("Style.IDENTIFIER", Config.getInstance().identifierColor + ", 0"); - configuration.put("Style.DEFAULT", Config.getInstance().defaultTextColor + ", 0"); - configuration.put(LineNumbersRuler.PROPERTY_BACKGROUND, Config.getInstance().lineNumbersBackground + ""); - configuration.put(LineNumbersRuler.PROPERTY_FOREGROUND, Config.getInstance().lineNumbersForeground + ""); - configuration.put(LineNumbersRuler.PROPERTY_CURRENT_BACK, Config.getInstance().lineNumbersSelected + ""); - configuration.put("RightMarginColumn", "999"); //No need to have a right margin, if someone wants it add a config - - configuration.put("Action.quick-find", "cuchaz.enigma.gui.QuickFindAction, menu F"); - } - - public static void invalidate(){ - configuration = null; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java deleted file mode 100644 index ed32469..0000000 --- a/src/main/java/cuchaz/enigma/gui/Gui.java +++ /dev/null @@ -1,1058 +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.*; -import java.awt.event.*; -import java.nio.file.Path; -import java.util.List; -import java.util.*; -import java.util.function.Function; - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Highlighter; -import javax.swing.tree.*; - -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import cuchaz.enigma.Constants; -import cuchaz.enigma.EnigmaProfile; -import cuchaz.enigma.ExceptionIgnorer; -import cuchaz.enigma.analysis.*; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.config.Themes; -import cuchaz.enigma.gui.dialog.CrashDialog; -import cuchaz.enigma.gui.dialog.JavadocDialog; -import cuchaz.enigma.gui.dialog.SearchDialog; -import cuchaz.enigma.gui.elements.CollapsibleTabbedPane; -import cuchaz.enigma.gui.elements.MenuBar; -import cuchaz.enigma.gui.elements.PopupMenuBar; -import cuchaz.enigma.gui.filechooser.FileChooserAny; -import cuchaz.enigma.gui.filechooser.FileChooserFolder; -import cuchaz.enigma.gui.highlight.BoxHighlightPainter; -import cuchaz.enigma.gui.highlight.SelectionHighlightPainter; -import cuchaz.enigma.gui.highlight.TokenHighlightType; -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.gui.util.History; -import cuchaz.enigma.network.packet.*; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Message; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; -import de.sciss.syntaxpane.DefaultSyntaxKit; - -public class Gui { - - public final PopupMenuBar popupMenu; - private final PanelObf obfPanel; - private final PanelDeobf deobfPanel; - - private final MenuBar menuBar; - // state - public History, Entry>> referenceHistory; - public EntryReference, Entry> renamingReference; - public EntryReference, Entry> cursorReference; - private boolean shouldNavigateOnClick; - private ConnectionState connectionState; - private boolean isJarOpen; - - public FileDialog jarFileChooser; - public FileDialog tinyMappingsFileChooser; - public SearchDialog searchDialog; - public JFileChooser enigmaMappingsFileChooser; - public JFileChooser exportSourceFileChooser; - public FileDialog exportJarFileChooser; - private GuiController controller; - private JFrame frame; - public Config.LookAndFeel editorFeel; - public PanelEditor editor; - public JScrollPane sourceScroller; - private JPanel classesPanel; - private JSplitPane splitClasses; - private PanelIdentifier infoPanel; - public Map boxHighlightPainters; - private SelectionHighlightPainter selectionHighlightPainter; - private JTree inheritanceTree; - private JTree implementationsTree; - private JTree callsTree; - private JList tokens; - private JTabbedPane tabs; - - private JSplitPane splitRight; - private JSplitPane logSplit; - private CollapsibleTabbedPane logTabs; - private JList users; - private DefaultListModel userModel; - private JScrollPane messageScrollPane; - private JList messages; - private DefaultListModel messageModel; - private JTextField chatBox; - - private JPanel statusBar; - private JLabel connectionStatusLabel; - private JLabel statusLabel; - - public JTextField renameTextField; - public JTextArea javadocTextArea; - - public void setEditorTheme(Config.LookAndFeel feel) { - if (editor != null && (editorFeel == null || editorFeel != feel)) { - editor.updateUI(); - editor.setBackground(new Color(Config.getInstance().editorBackground)); - if (editorFeel != null) { - getController().refreshCurrentClass(); - } - - editorFeel = feel; - } - } - - public Gui(EnigmaProfile profile) { - Config.getInstance().lookAndFeel.setGlobalLAF(); - - // init frame - 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(this.frame); - Thread.setDefaultUncaughtExceptionHandler((thread, t) -> { - t.printStackTrace(System.err); - if (!ExceptionIgnorer.shouldIgnore(t)) { - CrashDialog.show(t); - } - }); - } - - this.controller = new GuiController(this, profile); - - Themes.updateTheme(this); - - // init file choosers - this.jarFileChooser = new FileDialog(getFrame(), I18n.translate("menu.file.jar.open"), FileDialog.LOAD); - - this.tinyMappingsFileChooser = new FileDialog(getFrame(), "Open tiny Mappings", FileDialog.LOAD); - this.enigmaMappingsFileChooser = new FileChooserAny(); - this.exportSourceFileChooser = new FileChooserFolder(); - this.exportJarFileChooser = new FileDialog(getFrame(), I18n.translate("menu.file.export.jar"), FileDialog.SAVE); - - this.obfPanel = new PanelObf(this); - this.deobfPanel = new PanelDeobf(this); - - // set up classes panel (don't add the splitter yet) - splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, this.obfPanel, this.deobfPanel); - splitClasses.setResizeWeight(0.3); - this.classesPanel = new JPanel(); - this.classesPanel.setLayout(new BorderLayout()); - this.classesPanel.setPreferredSize(ScaleUtil.getDimension(250, 0)); - - // init info panel - infoPanel = new PanelIdentifier(this); - infoPanel.clearReference(); - - // init editor - selectionHighlightPainter = new SelectionHighlightPainter(); - this.editor = new PanelEditor(this); - this.sourceScroller = new JScrollPane(this.editor); - this.editor.setContentType("text/enigma-sources"); - this.editor.setBackground(new Color(Config.getInstance().editorBackground)); - DefaultSyntaxKit kit = (DefaultSyntaxKit) this.editor.getEditorKit(); - kit.toggleComponent(this.editor, "de.sciss.syntaxpane.components.TokenMarker"); - - // init editor popup menu - this.popupMenu = new PopupMenuBar(this); - this.editor.setComponentPopupMenu(this.popupMenu); - - // init inheritance panel - inheritanceTree = new JTree(); - inheritanceTree.setModel(null); - inheritanceTree.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { - // get the selected node - TreePath path = inheritanceTree.getSelectionPath(); - if (path == null) { - return; - } - - Object node = path.getLastPathComponent(); - if (node instanceof ClassInheritanceTreeNode) { - ClassInheritanceTreeNode classNode = (ClassInheritanceTreeNode) node; - controller.navigateTo(new ClassEntry(classNode.getObfClassName())); - } else if (node instanceof MethodInheritanceTreeNode) { - MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode) node; - if (methodNode.isImplemented()) { - controller.navigateTo(methodNode.getMethodEntry()); - } - } - } - } - }); - TreeCellRenderer cellRenderer = inheritanceTree.getCellRenderer(); - inheritanceTree.setCellRenderer(new MethodTreeCellRenderer(cellRenderer)); - - JPanel inheritancePanel = new JPanel(); - inheritancePanel.setLayout(new BorderLayout()); - inheritancePanel.add(new JScrollPane(inheritanceTree)); - - // init implementations panel - implementationsTree = new JTree(); - implementationsTree.setModel(null); - implementationsTree.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { - // get the selected node - TreePath path = implementationsTree.getSelectionPath(); - if (path == null) { - return; - } - - Object node = path.getLastPathComponent(); - if (node instanceof ClassImplementationsTreeNode) { - ClassImplementationsTreeNode classNode = (ClassImplementationsTreeNode) node; - controller.navigateTo(classNode.getClassEntry()); - } else if (node instanceof MethodImplementationsTreeNode) { - MethodImplementationsTreeNode methodNode = (MethodImplementationsTreeNode) node; - controller.navigateTo(methodNode.getMethodEntry()); - } - } - } - }); - JPanel implementationsPanel = new JPanel(); - implementationsPanel.setLayout(new BorderLayout()); - implementationsPanel.add(new JScrollPane(implementationsTree)); - - // init call panel - callsTree = new JTree(); - callsTree.setModel(null); - callsTree.addMouseListener(new MouseAdapter() { - @SuppressWarnings("unchecked") - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { - // get the selected node - TreePath path = callsTree.getSelectionPath(); - if (path == null) { - return; - } - - Object node = path.getLastPathComponent(); - if (node instanceof ReferenceTreeNode) { - ReferenceTreeNode, Entry> referenceNode = ((ReferenceTreeNode, Entry>) node); - if (referenceNode.getReference() != null) { - controller.navigateTo(referenceNode.getReference()); - } else { - controller.navigateTo(referenceNode.getEntry()); - } - } - } - } - }); - tokens = new JList<>(); - tokens.setCellRenderer(new TokenListCellRenderer(this.controller)); - tokens.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - tokens.setLayoutOrientation(JList.VERTICAL); - tokens.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() == 2) { - Token selected = tokens.getSelectedValue(); - if (selected != null) { - showToken(selected); - } - } - } - }); - tokens.setPreferredSize(ScaleUtil.getDimension(0, 200)); - tokens.setMinimumSize(ScaleUtil.getDimension(0, 200)); - JSplitPane callPanel = new JSplitPane( - JSplitPane.VERTICAL_SPLIT, - true, - new JScrollPane(callsTree), - new JScrollPane(tokens) - ); - callPanel.setResizeWeight(1); // let the top side take all the slack - callPanel.resetToPreferredSizes(); - - // layout controls - JPanel centerPanel = new JPanel(); - centerPanel.setLayout(new BorderLayout()); - centerPanel.add(infoPanel, BorderLayout.NORTH); - centerPanel.add(sourceScroller, BorderLayout.CENTER); - tabs = new JTabbedPane(); - tabs.setPreferredSize(ScaleUtil.getDimension(250, 0)); - tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel); - tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel); - tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel); - logTabs = new CollapsibleTabbedPane(JTabbedPane.BOTTOM); - userModel = new DefaultListModel<>(); - users = new JList<>(userModel); - messageModel = new DefaultListModel<>(); - messages = new JList<>(messageModel); - messages.setCellRenderer(new MessageListCellRenderer()); - JPanel messagePanel = new JPanel(new BorderLayout()); - messageScrollPane = new JScrollPane(this.messages); - messagePanel.add(messageScrollPane, BorderLayout.CENTER); - JPanel chatPanel = new JPanel(new BorderLayout()); - chatBox = new JTextField(); - AbstractAction sendListener = new AbstractAction("Send") { - @Override - public void actionPerformed(ActionEvent e) { - sendMessage(); - } - }; - chatBox.addActionListener(sendListener); - JButton chatSendButton = new JButton(sendListener); - chatPanel.add(chatBox, BorderLayout.CENTER); - chatPanel.add(chatSendButton, BorderLayout.EAST); - messagePanel.add(chatPanel, BorderLayout.SOUTH); - logTabs.addTab(I18n.translate("log_panel.users"), new JScrollPane(this.users)); - logTabs.addTab(I18n.translate("log_panel.messages"), messagePanel); - logSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, tabs, logTabs); - logSplit.setResizeWeight(0.5); - logSplit.resetToPreferredSizes(); - splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, this.logSplit); - splitRight.setResizeWeight(1); // let the left side take all the slack - splitRight.resetToPreferredSizes(); - 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 - this.menuBar = new MenuBar(this); - this.frame.setJMenuBar(this.menuBar); - - // init status bar - statusBar = new JPanel(new BorderLayout()); - statusBar.setBorder(BorderFactory.createLoweredBevelBorder()); - connectionStatusLabel = new JLabel(); - statusLabel = new JLabel(); - statusBar.add(statusLabel, BorderLayout.CENTER); - statusBar.add(connectionStatusLabel, BorderLayout.EAST); - pane.add(statusBar, BorderLayout.SOUTH); - - // init state - setConnectionState(ConnectionState.NOT_CONNECTED); - onCloseJar(); - - this.frame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent event) { - close(); - } - }); - - // show the frame - pane.doLayout(); - this.frame.setSize(ScaleUtil.getDimension(1024, 576)); - this.frame.setMinimumSize(ScaleUtil.getDimension(640, 480)); - this.frame.setVisible(true); - this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - this.frame.setLocationRelativeTo(null); - } - - public JFrame getFrame() { - return this.frame; - } - - public GuiController getController() { - return this.controller; - } - - public void onStartOpenJar() { - this.classesPanel.removeAll(); - redraw(); - } - - public void onFinishOpenJar(String jarName) { - // update gui - this.frame.setTitle(Constants.NAME + " - " + jarName); - this.classesPanel.removeAll(); - this.classesPanel.add(splitClasses); - setEditorText(null); - - // update menu - isJarOpen = true; - - updateUiState(); - redraw(); - } - - public void onCloseJar() { - - // update gui - this.frame.setTitle(Constants.NAME); - setObfClasses(null); - setDeobfClasses(null); - setEditorText(null); - this.classesPanel.removeAll(); - - // update menu - isJarOpen = false; - setMappingsFile(null); - - updateUiState(); - redraw(); - } - - public void setObfClasses(Collection obfClasses) { - this.obfPanel.obfClasses.setClasses(obfClasses); - } - - public void setDeobfClasses(Collection deobfClasses) { - this.deobfPanel.deobfClasses.setClasses(deobfClasses); - } - - public void setMappingsFile(Path path) { - this.enigmaMappingsFileChooser.setSelectedFile(path != null ? path.toFile() : null); - updateUiState(); - } - - public void setEditorText(String source) { - this.editor.getHighlighter().removeAllHighlights(); - this.editor.setText(source); - } - - public void setSource(DecompiledClassSource source) { - editor.setText(source.toString()); - setHighlightedTokens(source.getHighlightedTokens()); - } - - public void showToken(final Token token) { - if (token == null) { - throw new IllegalArgumentException("Token cannot be null!"); - } - CodeReader.navigateToToken(this.editor, token, selectionHighlightPainter); - redraw(); - } - - public void showTokens(Collection tokens) { - Vector sortedTokens = new Vector<>(tokens); - Collections.sort(sortedTokens); - if (sortedTokens.size() > 1) { - // sort the tokens and update the tokens panel - this.tokens.setListData(sortedTokens); - this.tokens.setSelectedIndex(0); - } else { - this.tokens.setListData(new Vector<>()); - } - - // show the first token - showToken(sortedTokens.get(0)); - } - - public void setHighlightedTokens(Map> tokens) { - // remove any old highlighters - this.editor.getHighlighter().removeAllHighlights(); - - if (boxHighlightPainters != null) { - for (TokenHighlightType type : tokens.keySet()) { - BoxHighlightPainter painter = boxHighlightPainters.get(type); - if (painter != null) { - setHighlightedTokens(tokens.get(type), painter); - } - } - } - - redraw(); - } - - private void setHighlightedTokens(Iterable tokens, Highlighter.HighlightPainter painter) { - for (Token token : tokens) { - try { - this.editor.getHighlighter().addHighlight(token.start, token.end, painter); - } catch (BadLocationException ex) { - throw new IllegalArgumentException(ex); - } - } - } - - private void showCursorReference(EntryReference, Entry> reference) { - if (reference == null) { - infoPanel.clearReference(); - return; - } - - this.cursorReference = reference; - - EntryReference, Entry> translatedReference = controller.project.getMapper().deobfuscate(reference); - - infoPanel.removeAll(); - if (translatedReference.entry instanceof ClassEntry) { - showClassEntry((ClassEntry) translatedReference.entry); - } else if (translatedReference.entry instanceof FieldEntry) { - showFieldEntry((FieldEntry) translatedReference.entry); - } else if (translatedReference.entry instanceof MethodEntry) { - showMethodEntry((MethodEntry) translatedReference.entry); - } else if (translatedReference.entry instanceof LocalVariableEntry) { - showLocalVariableEntry((LocalVariableEntry) translatedReference.entry); - } else { - throw new Error("Unknown entry desc: " + translatedReference.entry.getClass().getName()); - } - - redraw(); - } - - private void showLocalVariableEntry(LocalVariableEntry entry) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.variable"), entry.getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getContainingClass().getFullName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.method"), entry.getParent().getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.index"), Integer.toString(entry.getIndex())); - } - - private void showClassEntry(ClassEntry entry) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getFullName()); - addModifierComboBox(infoPanel, I18n.translate("info_panel.identifier.modifier"), entry); - } - - private void showFieldEntry(FieldEntry entry) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.field"), entry.getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getParent().getFullName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.type_descriptor"), entry.getDesc().toString()); - addModifierComboBox(infoPanel, I18n.translate("info_panel.identifier.modifier"), entry); - } - - private void showMethodEntry(MethodEntry entry) { - if (entry.isConstructor()) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.constructor"), entry.getParent().getFullName()); - } else { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.method"), entry.getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getParent().getFullName()); - } - addNameValue(infoPanel, I18n.translate("info_panel.identifier.method_descriptor"), entry.getDesc().toString()); - addModifierComboBox(infoPanel, I18n.translate("info_panel.identifier.modifier"), entry); - } - - private void addNameValue(JPanel container, String name, String value) { - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); - - JLabel label = new JLabel(name + ":", JLabel.RIGHT); - label.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height))); - panel.add(label); - - panel.add(Utils.unboldLabel(new JLabel(value, JLabel.LEFT))); - - container.add(panel); - } - - private JComboBox addModifierComboBox(JPanel container, String name, Entry entry) { - if (!getController().project.isRenamable(entry)) - return null; - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); - JLabel label = new JLabel(name + ":", JLabel.RIGHT); - label.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height))); - panel.add(label); - JComboBox combo = new JComboBox<>(AccessModifier.values()); - ((JLabel) combo.getRenderer()).setHorizontalAlignment(JLabel.LEFT); - combo.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height))); - - EntryMapping mapping = controller.project.getMapper().getDeobfMapping(entry); - if (mapping != null) { - combo.setSelectedIndex(mapping.getAccessModifier().ordinal()); - } else { - combo.setSelectedIndex(AccessModifier.UNCHANGED.ordinal()); - } - - combo.addItemListener(controller::modifierChange); - - panel.add(combo); - - container.add(panel); - - return combo; - } - - public void onCaretMove(int pos, boolean fromClick) { - if (controller.project == null) - return; - EntryRemapper mapper = controller.project.getMapper(); - Token token = this.controller.getToken(pos); - boolean isToken = token != null; - - cursorReference = this.controller.getReference(token); - Entry referenceEntry = cursorReference != null ? cursorReference.entry : null; - - if (referenceEntry != null && shouldNavigateOnClick && fromClick) { - shouldNavigateOnClick = false; - Entry navigationEntry = referenceEntry; - if (cursorReference.context == null) { - EntryResolver resolver = mapper.getObfResolver(); - navigationEntry = resolver.resolveFirstEntry(referenceEntry, ResolutionStrategy.RESOLVE_ROOT); - } - controller.navigateTo(navigationEntry); - return; - } - - boolean isClassEntry = isToken && referenceEntry instanceof ClassEntry; - boolean isFieldEntry = isToken && referenceEntry instanceof FieldEntry; - boolean isMethodEntry = isToken && referenceEntry instanceof MethodEntry && !((MethodEntry) referenceEntry).isConstructor(); - boolean isConstructorEntry = isToken && referenceEntry instanceof MethodEntry && ((MethodEntry) referenceEntry).isConstructor(); - boolean isRenamable = isToken && this.controller.project.isRenamable(cursorReference); - - if (!isRenaming()) { - if (isToken) { - showCursorReference(cursorReference); - } else { - infoPanel.clearReference(); - } - } - - this.popupMenu.renameMenu.setEnabled(isRenamable); - this.popupMenu.editJavadocMenu.setEnabled(isRenamable); - this.popupMenu.showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry); - this.popupMenu.showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry); - this.popupMenu.showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry); - this.popupMenu.showCallsSpecificMenu.setEnabled(isMethodEntry); - this.popupMenu.openEntryMenu.setEnabled(isRenamable && (isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry)); - this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousReference()); - this.popupMenu.openNextMenu.setEnabled(this.controller.hasNextReference()); - this.popupMenu.toggleMappingMenu.setEnabled(isRenamable); - - if (isToken && !Objects.equals(referenceEntry, mapper.deobfuscate(referenceEntry))) { - this.popupMenu.toggleMappingMenu.setText(I18n.translate("popup_menu.reset_obfuscated")); - } else { - this.popupMenu.toggleMappingMenu.setText(I18n.translate("popup_menu.mark_deobfuscated")); - } - } - - public void startDocChange() { - EntryReference, Entry> curReference = cursorReference; - if (isRenaming()) { - finishRename(false); - } - renamingReference = curReference; - - // init the text box - javadocTextArea = new JTextArea(10, 40); - - EntryReference, Entry> translatedReference = controller.project.getMapper().deobfuscate(cursorReference); - javadocTextArea.setText(Strings.nullToEmpty(translatedReference.entry.getJavadocs())); - - JavadocDialog.init(frame, javadocTextArea, this::finishDocChange); - javadocTextArea.grabFocus(); - - redraw(); - } - - private void finishDocChange(JFrame ui, boolean saveName) { - String newName = javadocTextArea.getText(); - if (saveName) { - try { - this.controller.changeDocs(renamingReference, newName); - this.controller.sendPacket(new ChangeDocsC2SPacket(renamingReference.getNameableEntry(), newName)); - } catch (IllegalNameException ex) { - javadocTextArea.setBorder(BorderFactory.createLineBorder(Color.red, 1)); - javadocTextArea.setToolTipText(ex.getReason()); - Utils.showToolTipNow(javadocTextArea); - return; - } - - ui.setVisible(false); - showCursorReference(cursorReference); - return; - } - - // abort the jd change - javadocTextArea = null; - ui.setVisible(false); - showCursorReference(cursorReference); - - this.editor.grabFocus(); - - redraw(); - } - - public void startRename() { - - // init the text box - renameTextField = new JTextField(); - - EntryReference, Entry> translatedReference = controller.project.getMapper().deobfuscate(cursorReference); - renameTextField.setText(translatedReference.getNameableName()); - - renameTextField.setPreferredSize(ScaleUtil.getDimension(360, ScaleUtil.invert(renameTextField.getPreferredSize().height))); - renameTextField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.VK_ENTER: - finishRename(true); - break; - - case KeyEvent.VK_ESCAPE: - finishRename(false); - break; - default: - break; - } - } - }); - - // find the label with the name and replace it with the text box - JPanel panel = (JPanel) infoPanel.getComponent(0); - panel.remove(panel.getComponentCount() - 1); - panel.add(renameTextField); - renameTextField.grabFocus(); - - int offset = renameTextField.getText().lastIndexOf('/') + 1; - // If it's a class and isn't in the default package, assume that it's deobfuscated. - if (translatedReference.getNameableEntry() instanceof ClassEntry && renameTextField.getText().contains("/") && offset != 0) - renameTextField.select(offset, renameTextField.getText().length()); - else - renameTextField.selectAll(); - - renamingReference = cursorReference; - - redraw(); - } - - private void finishRename(boolean saveName) { - String newName = renameTextField.getText(); - - if (saveName && newName != null && !newName.isEmpty()) { - try { - this.controller.rename(renamingReference, newName, true); - this.controller.sendPacket(new RenameC2SPacket(renamingReference.getNameableEntry(), newName, true)); - renameTextField = null; - } catch (IllegalNameException ex) { - renameTextField.setBorder(BorderFactory.createLineBorder(Color.red, 1)); - renameTextField.setToolTipText(ex.getReason()); - Utils.showToolTipNow(renameTextField); - } - return; - } - - renameTextField = null; - - // abort the rename - showCursorReference(cursorReference); - - this.editor.grabFocus(); - - redraw(); - } - - private boolean isRenaming() { - return renameTextField != null; - } - - public void showInheritance() { - - if (cursorReference == null) { - return; - } - - inheritanceTree.setModel(null); - - if (cursorReference.entry instanceof ClassEntry) { - // get the class inheritance - ClassInheritanceTreeNode classNode = this.controller.getClassInheritance((ClassEntry) cursorReference.entry); - - // show the tree at the root - TreePath path = getPathToRoot(classNode); - inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); - inheritanceTree.expandPath(path); - inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); - } else if (cursorReference.entry instanceof MethodEntry) { - // get the method inheritance - MethodInheritanceTreeNode classNode = this.controller.getMethodInheritance((MethodEntry) cursorReference.entry); - - // show the tree at the root - TreePath path = getPathToRoot(classNode); - inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); - inheritanceTree.expandPath(path); - inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); - } - - tabs.setSelectedIndex(0); - - redraw(); - } - - public void showImplementations() { - - if (cursorReference == null) { - return; - } - - implementationsTree.setModel(null); - - DefaultMutableTreeNode node = null; - - // get the class implementations - if (cursorReference.entry instanceof ClassEntry) - node = this.controller.getClassImplementations((ClassEntry) cursorReference.entry); - else // get the method implementations - if (cursorReference.entry instanceof MethodEntry) - node = this.controller.getMethodImplementations((MethodEntry) cursorReference.entry); - - if (node != null) { - // show the tree at the root - TreePath path = getPathToRoot(node); - implementationsTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); - implementationsTree.expandPath(path); - implementationsTree.setSelectionRow(implementationsTree.getRowForPath(path)); - } - - tabs.setSelectedIndex(1); - - redraw(); - } - - public void showCalls(boolean recurse) { - if (cursorReference == null) { - return; - } - - if (cursorReference.entry instanceof ClassEntry) { - ClassReferenceTreeNode node = this.controller.getClassReferences((ClassEntry) cursorReference.entry); - callsTree.setModel(new DefaultTreeModel(node)); - } else if (cursorReference.entry instanceof FieldEntry) { - FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) cursorReference.entry); - callsTree.setModel(new DefaultTreeModel(node)); - } else if (cursorReference.entry instanceof MethodEntry) { - MethodReferenceTreeNode node = this.controller.getMethodReferences((MethodEntry) cursorReference.entry, recurse); - callsTree.setModel(new DefaultTreeModel(node)); - } - - tabs.setSelectedIndex(2); - - redraw(); - } - - public void toggleMapping() { - Entry obfEntry = cursorReference.entry; - Entry deobfEntry = controller.project.getMapper().deobfuscate(obfEntry); - - if (!Objects.equals(obfEntry, deobfEntry)) { - this.controller.removeMapping(cursorReference); - this.controller.sendPacket(new RemoveMappingC2SPacket(cursorReference.getNameableEntry())); - } else { - this.controller.markAsDeobfuscated(cursorReference); - this.controller.sendPacket(new MarkDeobfuscatedC2SPacket(cursorReference.getNameableEntry())); - } - } - - private TreePath getPathToRoot(TreeNode node) { - List nodes = Lists.newArrayList(); - TreeNode n = node; - do { - nodes.add(n); - n = n.getParent(); - } while (n != null); - Collections.reverse(nodes); - return new TreePath(nodes.toArray()); - } - - public void showDiscardDiag(Function callback, String... options) { - int response = JOptionPane.showOptionDialog(this.frame, I18n.translate("prompt.close.summary"), I18n.translate("prompt.close.title"), JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE, null, options, options[2]); - callback.apply(response); - } - - public void saveMapping() { - if (this.enigmaMappingsFileChooser.getSelectedFile() != null || this.enigmaMappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION) - this.controller.saveMappings(this.enigmaMappingsFileChooser.getSelectedFile().toPath()); - } - - public void close() { - if (!this.controller.isDirty()) { - // everything is saved, we can exit safely - exit(); - } else { - // ask to save before closing - showDiscardDiag((response) -> { - if (response == JOptionPane.YES_OPTION) { - this.saveMapping(); - exit(); - } else if (response == JOptionPane.NO_OPTION) { - exit(); - } - - return null; - }, I18n.translate("prompt.close.save"), I18n.translate("prompt.close.discard"), I18n.translate("prompt.close.cancel")); - } - } - - private void exit() { - if (searchDialog != null) { - searchDialog.dispose(); - } - this.frame.dispose(); - System.exit(0); - } - - public void redraw() { - this.frame.validate(); - this.frame.repaint(); - } - - public void onPanelRename(Object prevData, Object data, DefaultMutableTreeNode node) throws IllegalNameException { - // package rename - if (data instanceof String) { - for (int i = 0; i < node.getChildCount(); i++) { - DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i); - ClassEntry prevDataChild = (ClassEntry) childNode.getUserObject(); - ClassEntry dataChild = new ClassEntry(data + "/" + prevDataChild.getSimpleName()); - this.controller.rename(new EntryReference<>(prevDataChild, prevDataChild.getFullName()), dataChild.getFullName(), false); - this.controller.sendPacket(new RenameC2SPacket(prevDataChild, dataChild.getFullName(), false)); - childNode.setUserObject(dataChild); - } - node.setUserObject(data); - // Ob package will never be modified, just reload deob view - this.deobfPanel.deobfClasses.reload(); - } - // class rename - else if (data instanceof ClassEntry) { - this.controller.rename(new EntryReference<>((ClassEntry) prevData, ((ClassEntry) prevData).getFullName()), ((ClassEntry) data).getFullName(), false); - this.controller.sendPacket(new RenameC2SPacket((ClassEntry) prevData, ((ClassEntry) data).getFullName(), false)); - } - } - - public void moveClassTree(EntryReference, Entry> obfReference, String newName) { - String oldEntry = obfReference.entry.getContainingClass().getPackageName(); - String newEntry = new ClassEntry(newName).getPackageName(); - moveClassTree(obfReference, oldEntry == null, newEntry == null); - } - - // TODO: getExpansionState will *not* actually update itself based on name changes! - public void moveClassTree(EntryReference, Entry> obfReference, boolean isOldOb, boolean isNewOb) { - ClassEntry classEntry = obfReference.entry.getContainingClass(); - - List stateDeobf = this.deobfPanel.deobfClasses.getExpansionState(this.deobfPanel.deobfClasses); - List stateObf = this.obfPanel.obfClasses.getExpansionState(this.obfPanel.obfClasses); - - // Ob -> deob - if (!isNewOb) { - this.deobfPanel.deobfClasses.moveClassIn(classEntry); - this.obfPanel.obfClasses.moveClassOut(classEntry); - this.deobfPanel.deobfClasses.reload(); - this.obfPanel.obfClasses.reload(); - } - // Deob -> ob - else if (!isOldOb) { - this.obfPanel.obfClasses.moveClassIn(classEntry); - this.deobfPanel.deobfClasses.moveClassOut(classEntry); - this.deobfPanel.deobfClasses.reload(); - this.obfPanel.obfClasses.reload(); - } - // Local move - else if (isOldOb) { - this.obfPanel.obfClasses.moveClassIn(classEntry); - this.obfPanel.obfClasses.reload(); - } else { - this.deobfPanel.deobfClasses.moveClassIn(classEntry); - this.deobfPanel.deobfClasses.reload(); - } - - this.deobfPanel.deobfClasses.restoreExpansionState(this.deobfPanel.deobfClasses, stateDeobf); - this.obfPanel.obfClasses.restoreExpansionState(this.obfPanel.obfClasses, stateObf); - } - - public PanelObf getObfPanel() { - return obfPanel; - } - - public PanelDeobf getDeobfPanel() { - return deobfPanel; - } - - public void setShouldNavigateOnClick(boolean shouldNavigateOnClick) { - this.shouldNavigateOnClick = shouldNavigateOnClick; - } - - public SearchDialog getSearchDialog() { - if (searchDialog == null) { - searchDialog = new SearchDialog(this); - } - return searchDialog; - } - - - public MenuBar getMenuBar() { - return menuBar; - } - - public void addMessage(Message message) { - JScrollBar verticalScrollBar = messageScrollPane.getVerticalScrollBar(); - boolean isAtBottom = verticalScrollBar.getValue() >= verticalScrollBar.getMaximum() - verticalScrollBar.getModel().getExtent(); - messageModel.addElement(message); - if (isAtBottom) { - SwingUtilities.invokeLater(() -> verticalScrollBar.setValue(verticalScrollBar.getMaximum() - verticalScrollBar.getModel().getExtent())); - } - statusLabel.setText(message.translate()); - } - - public void setUserList(List users) { - userModel.clear(); - users.forEach(userModel::addElement); - connectionStatusLabel.setText(String.format(I18n.translate("status.connected_user_count"), users.size())); - } - - private void sendMessage() { - String text = chatBox.getText().trim(); - if (!text.isEmpty()) { - getController().sendPacket(new MessageC2SPacket(text)); - } - chatBox.setText(""); - } - - /** - * Updates the state of the UI elements (button text, enabled state, ...) to reflect the current program state. - * This is a central place to update the UI state to prevent multiple code paths from changing the same state, - * causing inconsistencies. - */ - public void updateUiState() { - menuBar.connectToServerMenu.setEnabled(isJarOpen && connectionState != ConnectionState.HOSTING); - menuBar.connectToServerMenu.setText(I18n.translate(connectionState != ConnectionState.CONNECTED ? "menu.collab.connect" : "menu.collab.disconnect")); - menuBar.startServerMenu.setEnabled(isJarOpen && connectionState != ConnectionState.CONNECTED); - menuBar.startServerMenu.setText(I18n.translate(connectionState != ConnectionState.HOSTING ? "menu.collab.server.start" : "menu.collab.server.stop")); - - menuBar.closeJarMenu.setEnabled(isJarOpen); - menuBar.openMappingsMenus.forEach(item -> item.setEnabled(isJarOpen)); - menuBar.saveMappingsMenu.setEnabled(isJarOpen && enigmaMappingsFileChooser.getSelectedFile() != null && connectionState != ConnectionState.CONNECTED); - menuBar.saveMappingsMenus.forEach(item -> item.setEnabled(isJarOpen)); - menuBar.closeMappingsMenu.setEnabled(isJarOpen); - menuBar.exportSourceMenu.setEnabled(isJarOpen); - menuBar.exportJarMenu.setEnabled(isJarOpen); - - connectionStatusLabel.setText(I18n.translate(connectionState == ConnectionState.NOT_CONNECTED ? "status.disconnected" : "status.connected")); - - if (connectionState == ConnectionState.NOT_CONNECTED) { - logSplit.setLeftComponent(null); - splitRight.setRightComponent(tabs); - } else { - splitRight.setRightComponent(logSplit); - logSplit.setLeftComponent(tabs); - } - } - - public void setConnectionState(ConnectionState state) { - connectionState = state; - statusLabel.setText(I18n.translate("status.ready")); - updateUiState(); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java deleted file mode 100644 index cccc9e8..0000000 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ /dev/null @@ -1,729 +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 com.google.common.collect.Lists; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import cuchaz.enigma.Enigma; -import cuchaz.enigma.EnigmaProfile; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.analysis.*; -import cuchaz.enigma.api.service.ObfuscationTestService; -import cuchaz.enigma.bytecode.translators.SourceFixVisitor; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.gui.dialog.ProgressDialog; -import cuchaz.enigma.gui.stats.StatsGenerator; -import cuchaz.enigma.gui.stats.StatsMember; -import cuchaz.enigma.gui.util.History; -import cuchaz.enigma.network.EnigmaClient; -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.network.IntegratedEnigmaServer; -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.network.packet.LoginC2SPacket; -import cuchaz.enigma.network.packet.Packet; -import cuchaz.enigma.source.*; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Message; -import cuchaz.enigma.utils.ReadableToken; -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.tree.ClassNode; - -import javax.annotation.Nullable; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import java.awt.*; -import java.awt.event.ItemEvent; -import java.io.*; -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class GuiController { - private static final ExecutorService DECOMPILER_SERVICE = Executors.newSingleThreadExecutor( - new ThreadFactoryBuilder() - .setDaemon(true) - .setNameFormat("decompiler-thread") - .build() - ); - - private final Gui gui; - public final Enigma enigma; - - public EnigmaProject project; - private DecompilerService decompilerService; - private Decompiler decompiler; - private IndexTreeBuilder indexTreeBuilder; - - private Path loadedMappingPath; - private MappingFormat loadedMappingFormat; - - private DecompiledClassSource currentSource; - private Source uncommentedSource; - - private EnigmaClient client; - private EnigmaServer server; - - public GuiController(Gui gui, EnigmaProfile profile) { - this.gui = gui; - this.enigma = Enigma.builder() - .setProfile(profile) - .build(); - - decompilerService = Config.getInstance().decompiler.service; - } - - public boolean isDirty() { - return project != null && project.getMapper().isDirty(); - } - - public CompletableFuture openJar(final Path jarPath) { - this.gui.onStartOpenJar(); - - return ProgressDialog.runOffThread(gui.getFrame(), progress -> { - project = enigma.openJar(jarPath, progress); - indexTreeBuilder = new IndexTreeBuilder(project.getJarIndex()); - decompiler = createDecompiler(); - gui.onFinishOpenJar(jarPath.getFileName().toString()); - refreshClasses(); - }); - } - - private Decompiler createDecompiler() { - return decompilerService.create(name -> { - ClassNode node = project.getClassCache().getClassNode(name); - - if (node == null) { - return null; - } - - ClassNode fixedNode = new ClassNode(); - node.accept(new SourceFixVisitor(Utils.ASM_VERSION, fixedNode, project.getJarIndex())); - return fixedNode; - }, new SourceSettings(true, true)); - } - - public void closeJar() { - this.project = null; - this.gui.onCloseJar(); - } - - public CompletableFuture openMappings(MappingFormat format, Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - gui.setMappingsFile(path); - - return ProgressDialog.runOffThread(gui.getFrame(), progress -> { - try { - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - EntryTree mappings = format.read(path, progress, saveParameters); - project.setMappings(mappings); - - loadedMappingFormat = format; - loadedMappingPath = path; - - refreshClasses(); - refreshCurrentClass(); - } catch (MappingParseException e) { - JOptionPane.showMessageDialog(gui.getFrame(), e.getMessage()); - } - }); - } - - public void openMappings(EntryTree mappings) { - if (project == null) return; - - project.setMappings(mappings); - refreshClasses(); - refreshCurrentClass(); - } - - public CompletableFuture saveMappings(Path path) { - return saveMappings(path, loadedMappingFormat); - } - - public CompletableFuture saveMappings(Path path, MappingFormat format) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EntryRemapper mapper = project.getMapper(); - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - MappingDelta delta = mapper.takeMappingDelta(); - boolean saveAll = !path.equals(loadedMappingPath); - - loadedMappingFormat = format; - loadedMappingPath = path; - - if (saveAll) { - format.write(mapper.getObfToDeobf(), path, progress, saveParameters); - } else { - format.write(mapper.getObfToDeobf(), delta, path, progress, saveParameters); - } - }); - } - - public void closeMappings() { - if (project == null) return; - - project.setMappings(null); - - this.gui.setMappingsFile(null); - refreshClasses(); - refreshCurrentClass(); - } - - public CompletableFuture dropMappings() { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> project.dropMappings(progress)); - } - - public CompletableFuture exportSource(final Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - EnigmaProject.SourceExport source = jar.decompile(progress, decompilerService); - - source.write(path, progress); - }); - } - - public CompletableFuture exportJar(final Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - jar.write(path, progress); - }); - } - - public Token getToken(int pos) { - if (this.currentSource == null) { - return null; - } - return this.currentSource.getIndex().getReferenceToken(pos); - } - - @Nullable - public EntryReference, Entry> getReference(Token token) { - if (this.currentSource == null) { - return null; - } - return this.currentSource.getIndex().getReference(token); - } - - public ReadableToken getReadableToken(Token token) { - if (this.currentSource == null) { - return null; - } - - SourceIndex index = this.currentSource.getIndex(); - return new ReadableToken( - index.getLineNumber(token.start), - index.getColumnNumber(token.start), - index.getColumnNumber(token.end) - ); - } - - /** - * Navigates to the declaration with respect to navigation history - * - * @param entry the entry whose declaration will be navigated to - */ - public void openDeclaration(Entry entry) { - if (entry == null) { - throw new IllegalArgumentException("Entry cannot be null!"); - } - openReference(new EntryReference<>(entry, entry.getName())); - } - - /** - * Navigates to the reference with respect to navigation history - * - * @param reference the reference - */ - public void openReference(EntryReference, Entry> reference) { - if (reference == null) { - throw new IllegalArgumentException("Reference cannot be null!"); - } - if (this.gui.referenceHistory == null) { - this.gui.referenceHistory = new History<>(reference); - } else { - if (!reference.equals(this.gui.referenceHistory.getCurrent())) { - this.gui.referenceHistory.push(reference); - } - } - setReference(reference); - } - - /** - * Navigates to the reference without modifying history. If the class is not currently loaded, it will be loaded. - * - * @param reference the reference - */ - private void setReference(EntryReference, Entry> reference) { - // get the reference target class - ClassEntry classEntry = reference.getLocationClassEntry(); - if (!project.isRenamable(classEntry)) { - throw new IllegalArgumentException("Obfuscated class " + classEntry + " was not found in the jar!"); - } - - if (this.currentSource == null || !this.currentSource.getEntry().equals(classEntry)) { - // deobfuscate the class, then navigate to the reference - loadClass(classEntry, () -> showReference(reference)); - } else { - showReference(reference); - } - } - - /** - * Navigates to the reference without modifying history. Assumes the class is loaded. - * - * @param reference - */ - private void showReference(EntryReference, Entry> reference) { - Collection tokens = getTokensForReference(reference); - if (tokens.isEmpty()) { - // DEBUG - System.err.println(String.format("WARNING: no tokens found for %s in %s", reference, this.currentSource.getEntry())); - } else { - this.gui.showTokens(tokens); - } - } - - public Collection getTokensForReference(EntryReference, Entry> reference) { - EntryRemapper mapper = this.project.getMapper(); - - SourceIndex index = this.currentSource.getIndex(); - return mapper.getObfResolver().resolveReference(reference, ResolutionStrategy.RESOLVE_CLOSEST) - .stream() - .flatMap(r -> index.getReferenceTokens(r).stream()) - .collect(Collectors.toList()); - } - - public void openPreviousReference() { - if (hasPreviousReference()) { - setReference(gui.referenceHistory.goBack()); - } - } - - public boolean hasPreviousReference() { - return gui.referenceHistory != null && gui.referenceHistory.canGoBack(); - } - - public void openNextReference() { - if (hasNextReference()) { - setReference(gui.referenceHistory.goForward()); - } - } - - public boolean hasNextReference() { - return gui.referenceHistory != null && gui.referenceHistory.canGoForward(); - } - - public void navigateTo(Entry entry) { - if (!project.isRenamable(entry)) { - // entry is not in the jar. Ignore it - return; - } - openDeclaration(entry); - } - - public void navigateTo(EntryReference, Entry> reference) { - if (!project.isRenamable(reference.getLocationClassEntry())) { - return; - } - openReference(reference); - } - - private void refreshClasses() { - List obfClasses = Lists.newArrayList(); - List deobfClasses = Lists.newArrayList(); - this.addSeparatedClasses(obfClasses, deobfClasses); - this.gui.setObfClasses(obfClasses); - this.gui.setDeobfClasses(deobfClasses); - } - - public void addSeparatedClasses(List obfClasses, List deobfClasses) { - EntryRemapper mapper = project.getMapper(); - - Collection classes = project.getJarIndex().getEntryIndex().getClasses(); - Stream visibleClasses = classes.stream() - .filter(entry -> !entry.isInnerClass()); - - visibleClasses.forEach(entry -> { - ClassEntry deobfEntry = mapper.deobfuscate(entry); - - List obfService = enigma.getServices().get(ObfuscationTestService.TYPE); - boolean obfuscated = deobfEntry.equals(entry); - - if (obfuscated && !obfService.isEmpty()) { - if (obfService.stream().anyMatch(service -> service.testDeobfuscated(entry))) { - obfuscated = false; - } - } - - if (obfuscated) { - obfClasses.add(entry); - } else { - deobfClasses.add(entry); - } - }); - } - - public void refreshCurrentClass() { - refreshCurrentClass(null); - } - - private void refreshCurrentClass(EntryReference, Entry> reference) { - refreshCurrentClass(reference, RefreshMode.MINIMAL); - } - - private void refreshCurrentClass(EntryReference, Entry> reference, RefreshMode mode) { - if (currentSource != null) { - if (reference == null) { - int obfSelectionStart = currentSource.getObfuscatedOffset(gui.editor.getSelectionStart()); - int obfSelectionEnd = currentSource.getObfuscatedOffset(gui.editor.getSelectionEnd()); - - Rectangle viewportBounds = gui.sourceScroller.getViewport().getViewRect(); - // Here we pick an "anchor position", which we want to stay in the same vertical location on the screen after the new text has been set - int anchorModelPos = gui.editor.getSelectionStart(); - Rectangle anchorViewPos = Utils.safeModelToView(gui.editor, anchorModelPos); - if (anchorViewPos.y < viewportBounds.y || anchorViewPos.y >= viewportBounds.y + viewportBounds.height) { - anchorModelPos = gui.editor.viewToModel(new Point(0, viewportBounds.y)); - anchorViewPos = Utils.safeModelToView(gui.editor, anchorModelPos); - } - int obfAnchorPos = currentSource.getObfuscatedOffset(anchorModelPos); - Rectangle anchorViewPos_f = anchorViewPos; - int scrollX = gui.sourceScroller.getHorizontalScrollBar().getValue(); - - loadClass(currentSource.getEntry(), () -> SwingUtilities.invokeLater(() -> { - int newAnchorModelPos = currentSource.getDeobfuscatedOffset(obfAnchorPos); - Rectangle newAnchorViewPos = Utils.safeModelToView(gui.editor, newAnchorModelPos); - int newScrollY = newAnchorViewPos.y - (anchorViewPos_f.y - viewportBounds.y); - - gui.editor.select(currentSource.getDeobfuscatedOffset(obfSelectionStart), currentSource.getDeobfuscatedOffset(obfSelectionEnd)); - // Changing the selection scrolls to the caret position inside a SwingUtilities.invokeLater call, so - // we need to wrap our change to the scroll position inside another invokeLater so it happens after - // the caret's own scrolling. - SwingUtilities.invokeLater(() -> { - gui.sourceScroller.getHorizontalScrollBar().setValue(Math.min(scrollX, gui.sourceScroller.getHorizontalScrollBar().getMaximum())); - gui.sourceScroller.getVerticalScrollBar().setValue(Math.min(newScrollY, gui.sourceScroller.getVerticalScrollBar().getMaximum())); - }); - }), mode); - } else { - loadClass(currentSource.getEntry(), () -> showReference(reference), mode); - } - } - } - - private void loadClass(ClassEntry classEntry, Runnable callback) { - loadClass(classEntry, callback, RefreshMode.MINIMAL); - } - - private void loadClass(ClassEntry classEntry, Runnable callback, RefreshMode mode) { - ClassEntry targetClass = classEntry.getOutermostClass(); - - boolean requiresDecompile = mode == RefreshMode.FULL || currentSource == null || !currentSource.getEntry().equals(targetClass); - if (requiresDecompile) { - currentSource = null; // Or the GUI may try to find a nonexistent token - gui.setEditorText(I18n.translate("info_panel.editor.class.decompiling")); - } - - DECOMPILER_SERVICE.submit(() -> { - try { - if (requiresDecompile || mode == RefreshMode.JAVADOCS) { - currentSource = decompileSource(targetClass, mode == RefreshMode.JAVADOCS); - } - - remapSource(project.getMapper().getDeobfuscator()); - callback.run(); - } catch (Throwable t) { - System.err.println("An exception was thrown while decompiling class " + classEntry.getFullName()); - t.printStackTrace(System.err); - } - }); - } - - private DecompiledClassSource decompileSource(ClassEntry targetClass, boolean onlyRefreshJavadocs) { - try { - if (!onlyRefreshJavadocs || currentSource == null || !currentSource.getEntry().equals(targetClass)) { - uncommentedSource = decompiler.getSource(targetClass.getFullName()); - } - - Source source = uncommentedSource.addJavadocs(project.getMapper()); - - if (source == null) { - gui.setEditorText(I18n.translate("info_panel.editor.class.not_found") + " " + targetClass); - return DecompiledClassSource.text(targetClass, "Unable to find class"); - } - - SourceIndex index = source.index(); - index.resolveReferences(project.getMapper().getObfResolver()); - - return new DecompiledClassSource(targetClass, index); - } catch (Throwable t) { - StringWriter traceWriter = new StringWriter(); - t.printStackTrace(new PrintWriter(traceWriter)); - - return DecompiledClassSource.text(targetClass, traceWriter.toString()); - } - } - - private void remapSource(Translator translator) { - if (currentSource == null) { - return; - } - - currentSource.remapSource(project, translator); - - gui.setEditorTheme(Config.getInstance().lookAndFeel); - gui.setSource(currentSource); - } - - public void modifierChange(ItemEvent event) { - if (event.getStateChange() == ItemEvent.SELECTED) { - EntryRemapper mapper = project.getMapper(); - Entry entry = gui.cursorReference.entry; - AccessModifier modifier = (AccessModifier) event.getItem(); - - EntryMapping mapping = mapper.getDeobfMapping(entry); - if (mapping != null) { - mapper.mapFromObf(entry, new EntryMapping(mapping.getTargetName(), modifier)); - } else { - mapper.mapFromObf(entry, new EntryMapping(entry.getName(), modifier)); - } - - refreshCurrentClass(); - } - } - - public ClassInheritanceTreeNode getClassInheritance(ClassEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - ClassInheritanceTreeNode rootNode = indexTreeBuilder.buildClassInheritance(translator, entry); - return ClassInheritanceTreeNode.findNode(rootNode, entry); - } - - public ClassImplementationsTreeNode getClassImplementations(ClassEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - return this.indexTreeBuilder.buildClassImplementations(translator, entry); - } - - public MethodInheritanceTreeNode getMethodInheritance(MethodEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - MethodInheritanceTreeNode rootNode = indexTreeBuilder.buildMethodInheritance(translator, entry); - return MethodInheritanceTreeNode.findNode(rootNode, entry); - } - - public MethodImplementationsTreeNode getMethodImplementations(MethodEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - List rootNodes = indexTreeBuilder.buildMethodImplementations(translator, entry); - if (rootNodes.isEmpty()) { - return null; - } - if (rootNodes.size() > 1) { - System.err.println("WARNING: Method " + entry + " implements multiple interfaces. Only showing first one."); - } - return MethodImplementationsTreeNode.findNode(rootNodes.get(0), entry); - } - - public ClassReferenceTreeNode getClassReferences(ClassEntry entry) { - Translator deobfuscator = project.getMapper().getDeobfuscator(); - ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(deobfuscator, entry); - rootNode.load(project.getJarIndex(), true); - return rootNode; - } - - public FieldReferenceTreeNode getFieldReferences(FieldEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(translator, entry); - rootNode.load(project.getJarIndex(), true); - return rootNode; - } - - public MethodReferenceTreeNode getMethodReferences(MethodEntry entry, boolean recursive) { - Translator translator = project.getMapper().getDeobfuscator(); - MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(translator, entry); - rootNode.load(project.getJarIndex(), true, recursive); - return rootNode; - } - - public void rename(EntryReference, Entry> reference, String newName, boolean refreshClassTree) { - rename(reference, newName, refreshClassTree, true); - } - - public void rename(EntryReference, Entry> reference, String newName, boolean refreshClassTree, boolean jumpToReference) { - Entry entry = reference.getNameableEntry(); - project.getMapper().mapFromObf(entry, new EntryMapping(newName)); - - if (refreshClassTree && reference.entry instanceof ClassEntry && !((ClassEntry) reference.entry).isInnerClass()) - this.gui.moveClassTree(reference, newName); - - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void removeMapping(EntryReference, Entry> reference) { - removeMapping(reference, true); - } - - public void removeMapping(EntryReference, Entry> reference, boolean jumpToReference) { - project.getMapper().removeByObf(reference.getNameableEntry()); - - if (reference.entry instanceof ClassEntry) - this.gui.moveClassTree(reference, false, true); - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void changeDocs(EntryReference, Entry> reference, String updatedDocs) { - changeDocs(reference, updatedDocs, true); - } - - public void changeDocs(EntryReference, Entry> reference, String updatedDocs, boolean jumpToReference) { - changeDoc(reference.entry, Utils.isBlank(updatedDocs) ? null : updatedDocs); - - refreshCurrentClass(jumpToReference ? reference : null, RefreshMode.JAVADOCS); - } - - private void changeDoc(Entry obfEntry, String newDoc) { - EntryRemapper mapper = project.getMapper(); - if (mapper.getDeobfMapping(obfEntry) == null) { - markAsDeobfuscated(obfEntry, false); // NPE - } - mapper.mapFromObf(obfEntry, mapper.getDeobfMapping(obfEntry).withDocs(newDoc), false); - } - - private void markAsDeobfuscated(Entry obfEntry, boolean renaming) { - EntryRemapper mapper = project.getMapper(); - mapper.mapFromObf(obfEntry, new EntryMapping(mapper.deobfuscate(obfEntry).getName()), renaming); - } - - public void markAsDeobfuscated(EntryReference, Entry> reference) { - markAsDeobfuscated(reference, true); - } - - public void markAsDeobfuscated(EntryReference, Entry> reference, boolean jumpToReference) { - EntryRemapper mapper = project.getMapper(); - Entry entry = reference.getNameableEntry(); - mapper.mapFromObf(entry, new EntryMapping(mapper.deobfuscate(entry).getName())); - - if (reference.entry instanceof ClassEntry && !((ClassEntry) reference.entry).isInnerClass()) - this.gui.moveClassTree(reference, true, false); - - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void openStats(Set includedMembers) { - ProgressDialog.runOffThread(gui.getFrame(), progress -> { - String data = new StatsGenerator(project).generate(progress, includedMembers); - - try { - File statsFile = File.createTempFile("stats", ".html"); - - try (FileWriter w = new FileWriter(statsFile)) { - w.write( - Utils.readResourceToString("/stats.html") - .replace("/*data*/", data) - ); - } - - Desktop.getDesktop().open(statsFile); - } catch (IOException e) { - throw new Error(e); - } - }); - } - - public void setDecompiler(DecompilerService service) { - uncommentedSource = null; - decompilerService = service; - decompiler = createDecompiler(); - refreshCurrentClass(null, RefreshMode.FULL); - } - - public EnigmaClient getClient() { - return client; - } - - public EnigmaServer getServer() { - return server; - } - - public void createClient(String username, String ip, int port, char[] password) throws IOException { - client = new EnigmaClient(this, ip, port); - client.connect(); - client.sendPacket(new LoginC2SPacket(project.getJarChecksum(), password, username)); - gui.setConnectionState(ConnectionState.CONNECTED); - } - - public void createServer(int port, char[] password) throws IOException { - server = new IntegratedEnigmaServer(project.getJarChecksum(), password, EntryRemapper.mapped(project.getJarIndex(), new HashEntryTree<>(project.getMapper().getObfToDeobf())), port); - server.start(); - client = new EnigmaClient(this, "127.0.0.1", port); - client.connect(); - client.sendPacket(new LoginC2SPacket(project.getJarChecksum(), password, EnigmaServer.OWNER_USERNAME)); - gui.setConnectionState(ConnectionState.HOSTING); - } - - public synchronized void disconnectIfConnected(String reason) { - if (client == null && server == null) { - return; - } - - if (client != null) { - client.disconnect(); - } - if (server != null) { - server.stop(); - } - client = null; - server = null; - SwingUtilities.invokeLater(() -> { - if (reason != null) { - JOptionPane.showMessageDialog(gui.getFrame(), I18n.translate(reason), I18n.translate("disconnect.disconnected"), JOptionPane.INFORMATION_MESSAGE); - } - gui.setConnectionState(ConnectionState.NOT_CONNECTED); - }); - } - - public void sendPacket(Packet packet) { - if (client != null) { - client.sendPacket(packet); - } - } - - public void addMessage(Message message) { - gui.addMessage(message); - } - - public void updateUserList(List users) { - gui.setUserList(users); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java b/src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java deleted file mode 100644 index c9e38cb..0000000 --- a/src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java +++ /dev/null @@ -1,24 +0,0 @@ -package cuchaz.enigma.gui; - -import java.awt.Component; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; - -import cuchaz.enigma.utils.Message; - -// For now, just render the translated text. -// TODO: Icons or something later? -public class MessageListCellRenderer extends DefaultListCellRenderer { - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - Message message = (Message) value; - if (message != null) { - setText(message.translate()); - } - return this; - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java b/src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java deleted file mode 100644 index 05d90a9..0000000 --- a/src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java +++ /dev/null @@ -1,42 +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 cuchaz.enigma.analysis.MethodInheritanceTreeNode; -import cuchaz.enigma.config.Config; - -import javax.swing.*; -import javax.swing.tree.TreeCellRenderer; -import java.awt.*; - -class MethodTreeCellRenderer implements TreeCellRenderer { - - private final TreeCellRenderer parent; - - MethodTreeCellRenderer(TreeCellRenderer parent) { - this.parent = parent; - } - - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { - Component ret = parent.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); - Config config = Config.getInstance(); - if (!(value instanceof MethodInheritanceTreeNode) || ((MethodInheritanceTreeNode) value).isImplemented()) { - ret.setForeground(new Color(config.defaultTextColor)); - ret.setFont(ret.getFont().deriveFont(Font.PLAIN)); - } else { - ret.setForeground(new Color(config.numberColor)); - ret.setFont(ret.getFont().deriveFont(Font.ITALIC)); - } - return ret; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/QuickFindAction.java b/src/main/java/cuchaz/enigma/gui/QuickFindAction.java deleted file mode 100644 index b7fa2eb..0000000 --- a/src/main/java/cuchaz/enigma/gui/QuickFindAction.java +++ /dev/null @@ -1,45 +0,0 @@ -package cuchaz.enigma.gui; - -import de.sciss.syntaxpane.SyntaxDocument; -import de.sciss.syntaxpane.actions.DefaultSyntaxAction; - -import javax.swing.text.JTextComponent; -import java.awt.event.ActionEvent; - -public final class QuickFindAction extends DefaultSyntaxAction { - public QuickFindAction() { - super("quick-find"); - } - - @Override - public void actionPerformed(JTextComponent target, SyntaxDocument document, int dot, ActionEvent event) { - Data data = Data.get(target); - data.showFindDialog(target); - } - - private static class Data { - private static final String KEY = "enigma-find-data"; - private EnigmaQuickFindDialog findDialog; - - private Data() { - } - - public static Data get(JTextComponent target) { - Object o = target.getDocument().getProperty(KEY); - if (o instanceof Data) { - return (Data) o; - } - - Data data = new Data(); - target.getDocument().putProperty(KEY, data); - return data; - } - - public void showFindDialog(JTextComponent target) { - if (findDialog == null) { - findDialog = new EnigmaQuickFindDialog(target); - } - findDialog.showFor(target); - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/RefreshMode.java b/src/main/java/cuchaz/enigma/gui/RefreshMode.java deleted file mode 100644 index 87cb83b..0000000 --- a/src/main/java/cuchaz/enigma/gui/RefreshMode.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.gui; - -public enum RefreshMode { - MINIMAL, - JAVADOCS, - FULL -} diff --git a/src/main/java/cuchaz/enigma/gui/SourceRemapper.java b/src/main/java/cuchaz/enigma/gui/SourceRemapper.java deleted file mode 100644 index f38f44e..0000000 --- a/src/main/java/cuchaz/enigma/gui/SourceRemapper.java +++ /dev/null @@ -1,64 +0,0 @@ -package cuchaz.enigma.gui; - -import cuchaz.enigma.analysis.Token; - -import java.util.HashMap; -import java.util.Map; - -public class SourceRemapper { - private final String source; - private final Iterable tokens; - - public SourceRemapper(String source, Iterable tokens) { - this.source = source; - this.tokens = tokens; - } - - public Result remap(Remapper remapper) { - StringBuffer remappedSource = new StringBuffer(source); - Map remappedTokens = new HashMap<>(); - - int accumulatedOffset = 0; - for (Token token : tokens) { - Token movedToken = token.move(accumulatedOffset); - - String remappedName = remapper.remap(token, movedToken); - if (remappedName != null) { - accumulatedOffset += movedToken.getRenameOffset(remappedName); - movedToken.rename(remappedSource, remappedName); - } - - if (!token.equals(movedToken)) { - remappedTokens.put(token, movedToken); - } - } - - return new Result(remappedSource.toString(), remappedTokens); - } - - public static class Result { - private final String remappedSource; - private final Map remappedTokens; - - Result(String remappedSource, Map remappedTokens) { - this.remappedSource = remappedSource; - this.remappedTokens = remappedTokens; - } - - public String getSource() { - return remappedSource; - } - - public Token getRemappedToken(Token token) { - return remappedTokens.getOrDefault(token, token); - } - - public boolean isEmpty() { - return remappedTokens.isEmpty(); - } - } - - public interface Remapper { - String remap(Token token, Token movedToken); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java b/src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java deleted file mode 100644 index 7375111..0000000 --- a/src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java +++ /dev/null @@ -1,35 +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 cuchaz.enigma.analysis.Token; - -import javax.swing.*; -import java.awt.*; - -public class TokenListCellRenderer implements ListCellRenderer { - - private GuiController controller; - private DefaultListCellRenderer defaultRenderer; - - public TokenListCellRenderer(GuiController controller) { - this.controller = controller; - this.defaultRenderer = new DefaultListCellRenderer(); - } - - @Override - public Component getListCellRendererComponent(JList list, Token token, int index, boolean isSelected, boolean hasFocus) { - JLabel label = (JLabel) this.defaultRenderer.getListCellRendererComponent(list, token, index, isSelected, hasFocus); - label.setText(this.controller.getReadableToken(token).toString()); - return label; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java deleted file mode 100644 index 43b8265..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java +++ /dev/null @@ -1,69 +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.dialog; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; -import java.io.IOException; - -public class AboutDialog { - - public static void show(JFrame parent) { - // init frame - final JFrame frame = new JFrame(String.format(I18n.translate("menu.help.about.title"), Constants.NAME)); - final Container pane = frame.getContentPane(); - pane.setLayout(new FlowLayout()); - - // load the content - try { - String html = Utils.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 -> Utils.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(I18n.translate("menu.help.about.ok")); - pane.add(okButton); - okButton.addActionListener(arg0 -> frame.dispose()); - - // show the frame - pane.doLayout(); - frame.setSize(ScaleUtil.getDimension(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/ChangeDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java deleted file mode 100644 index 64219ab..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java +++ /dev/null @@ -1,50 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import java.awt.BorderLayout; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; - -public class ChangeDialog { - - public static void show(Gui gui) { - // init frame - JFrame frame = new JFrame(I18n.translate("menu.view.change.title")); - JPanel textPanel = new JPanel(); - JPanel buttonPanel = new JPanel(); - frame.setLayout(new BorderLayout()); - frame.add(BorderLayout.NORTH, textPanel); - frame.add(BorderLayout.SOUTH, buttonPanel); - - // show text - JLabel text = new JLabel((I18n.translate("menu.view.change.summary"))); - text.setHorizontalAlignment(JLabel.CENTER); - textPanel.add(text); - - // show ok button - JButton okButton = new JButton(I18n.translate("menu.view.change.ok")); - buttonPanel.add(okButton); - okButton.addActionListener(event -> frame.dispose()); - okButton.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - frame.dispose(); - } - } - }); - - // show the frame - frame.pack(); - frame.setVisible(true); - frame.setResizable(false); - frame.setLocationRelativeTo(gui.getFrame()); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java deleted file mode 100644 index c5f505c..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ /dev/null @@ -1,82 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.Frame; - -public class ConnectToServerDialog { - - public static Result show(Frame parentComponent) { - JTextField usernameField = new JTextField(System.getProperty("user.name"), 20); - JPanel usernameRow = new JPanel(); - usernameRow.add(new JLabel(I18n.translate("prompt.connect.username"))); - usernameRow.add(usernameField); - JTextField ipField = new JTextField(20); - JPanel ipRow = new JPanel(); - ipRow.add(new JLabel(I18n.translate("prompt.connect.ip"))); - ipRow.add(ipField); - JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); - JPanel portRow = new JPanel(); - portRow.add(new JLabel(I18n.translate("prompt.port"))); - portRow.add(portField); - JPasswordField passwordField = new JPasswordField(20); - JPanel passwordRow = new JPanel(); - passwordRow.add(new JLabel(I18n.translate("prompt.password"))); - passwordRow.add(passwordField); - - int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{usernameRow, ipRow, portRow, passwordRow}, I18n.translate("prompt.connect.title"), JOptionPane.OK_CANCEL_OPTION); - if (response != JOptionPane.OK_OPTION) { - return null; - } - - String username = usernameField.getText(); - String ip = ipField.getText(); - int port; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - if (port < 0 || port >= 65536) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - char[] password = passwordField.getPassword(); - - return new Result(username, ip, port, password); - } - - public static class Result { - private final String username; - private final String ip; - private final int port; - private final char[] password; - - public Result(String username, String ip, int port, char[] password) { - this.username = username; - this.ip = ip; - this.port = port; - this.password = password; - } - - public String getUsername() { - return username; - } - - public String getIp() { - return ip; - } - - public int getPort() { - return port; - } - - public char[] getPassword() { - return password; - } - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java deleted file mode 100644 index 908b42e..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java +++ /dev/null @@ -1,105 +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.dialog; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.FileWriter; -import java.io.File; -import java.io.IOException; - -public class CrashDialog { - - private static CrashDialog instance = null; - - private JFrame frame; - private JTextArea text; - - private CrashDialog(JFrame parent) { - // init frame - frame = new JFrame(String.format(I18n.translate("crash.title"), Constants.NAME)); - final Container pane = frame.getContentPane(); - pane.setLayout(new BorderLayout()); - - JLabel label = new JLabel(String.format(I18n.translate("crash.summary"), Constants.NAME)); - label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - pane.add(label, BorderLayout.NORTH); - - // report panel - text = new JTextArea(); - text.setTabSize(2); - pane.add(new JScrollPane(text), BorderLayout.CENTER); - - // buttons panel - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.LINE_AXIS)); - JButton exportButton = new JButton(I18n.translate("crash.export")); - exportButton.addActionListener(event -> { - JFileChooser chooser = new JFileChooser(); - chooser.setSelectedFile(new File("enigma_crash.log")); - if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { - try { - File file = chooser.getSelectedFile(); - FileWriter writer = new FileWriter(file); - writer.write(instance.text.getText()); - writer.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - }); - buttonsPanel.add(exportButton); - buttonsPanel.add(Box.createHorizontalGlue()); - buttonsPanel.add(Utils.unboldLabel(new JLabel(I18n.translate("crash.exit.warning")))); - JButton ignoreButton = new JButton(I18n.translate("crash.ignore")); - ignoreButton.addActionListener(event -> { - // close (hide) the dialog - frame.setVisible(false); - }); - buttonsPanel.add(ignoreButton); - JButton exitButton = new JButton(I18n.translate("crash.exit")); - exitButton.addActionListener(event -> { - // exit enigma - System.exit(1); - }); - buttonsPanel.add(exitButton); - pane.add(buttonsPanel, BorderLayout.SOUTH); - - // show the frame - frame.setSize(ScaleUtil.getDimension(600, 400)); - frame.setLocationRelativeTo(parent); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } - - public static void init(JFrame parent) { - 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! - instance.text.setText(report); - instance.frame.doLayout(); - instance.frame.setVisible(true); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java deleted file mode 100644 index eea1dff..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java +++ /dev/null @@ -1,65 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.*; - -public class CreateServerDialog { - - public static Result show(Frame parentComponent) { - JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); - JPanel portRow = new JPanel(); - portRow.add(new JLabel(I18n.translate("prompt.port"))); - portRow.add(portField); - JPasswordField passwordField = new JPasswordField(20); - JPanel passwordRow = new JPanel(); - passwordRow.add(new JLabel(I18n.translate("prompt.password"))); - passwordRow.add(passwordField); - - int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{portRow, passwordRow}, I18n.translate("prompt.create_server.title"), JOptionPane.OK_CANCEL_OPTION); - if (response != JOptionPane.OK_OPTION) { - return null; - } - - int port; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - if (port < 0 || port >= 65536) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - - char[] password = passwordField.getPassword(); - if (password.length > EnigmaServer.MAX_PASSWORD_LENGTH) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.password.too_long"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - - return new Result(port, password); - } - - public static class Result { - private final int port; - private final char[] password; - - public Result(int port, char[] password) { - this.port = port; - this.password = password; - } - - public int getPort() { - return port; - } - - public char[] getPassword() { - return password; - } - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java deleted file mode 100644 index 7e41441..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java +++ /dev/null @@ -1,159 +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.dialog; - -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import javax.swing.text.html.HTML; - -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; - -public class JavadocDialog { - - private static JavadocDialog instance = null; - - private JFrame frame; - - private JavadocDialog(JFrame parent, JTextArea text, Callback callback) { - // init frame - frame = new JFrame(I18n.translate("javadocs.edit")); - final Container pane = frame.getContentPane(); - pane.setLayout(new BorderLayout()); - - // editor panel - text.setTabSize(2); - pane.add(new JScrollPane(text), BorderLayout.CENTER); - text.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.VK_ENTER: - if (event.isControlDown()) - callback.closeUi(frame, true); - break; - case KeyEvent.VK_ESCAPE: - callback.closeUi(frame, false); - break; - default: - break; - } - } - }); - - // buttons panel - JPanel buttonsPanel = new JPanel(); - FlowLayout buttonsLayout = new FlowLayout(); - buttonsLayout.setAlignment(FlowLayout.RIGHT); - buttonsPanel.setLayout(buttonsLayout); - buttonsPanel.add(Utils.unboldLabel(new JLabel(I18n.translate("javadocs.instruction")))); - JButton cancelButton = new JButton(I18n.translate("javadocs.cancel")); - cancelButton.addActionListener(event -> { - // close (hide) the dialog - callback.closeUi(frame, false); - }); - buttonsPanel.add(cancelButton); - JButton saveButton = new JButton(I18n.translate("javadocs.save")); - saveButton.addActionListener(event -> { - // exit enigma - callback.closeUi(frame, true); - }); - buttonsPanel.add(saveButton); - pane.add(buttonsPanel, BorderLayout.SOUTH); - - // tags panel - JMenuBar tagsMenu = new JMenuBar(); - - // add javadoc tags - for (JavadocTag tag : JavadocTag.values()) { - JButton tagButton = new JButton(tag.getText()); - tagButton.addActionListener(action -> { - boolean textSelected = text.getSelectedText() != null; - String tagText = tag.isInline() ? "{" + tag.getText() + " }" : tag.getText() + " "; - - if (textSelected) { - if (tag.isInline()) { - tagText = "{" + tag.getText() + " " + text.getSelectedText() + "}"; - } else { - tagText = tag.getText() + " " + text.getSelectedText(); - } - text.replaceSelection(tagText); - } else { - text.insert(tagText, text.getCaretPosition()); - } - - if (tag.isInline()) { - text.setCaretPosition(text.getCaretPosition() - 1); - } - text.grabFocus(); - }); - tagsMenu.add(tagButton); - } - - // add html tags - JComboBox htmlList = new JComboBox(); - htmlList.setPreferredSize(new Dimension()); - for (HTML.Tag htmlTag : HTML.getAllTags()) { - htmlList.addItem(htmlTag.toString()); - } - htmlList.addActionListener(action -> { - String tagText = "<" + htmlList.getSelectedItem().toString() + ">"; - text.insert(tagText, text.getCaretPosition()); - text.grabFocus(); - }); - tagsMenu.add(htmlList); - - pane.add(tagsMenu, BorderLayout.NORTH); - - // show the frame - frame.setSize(ScaleUtil.getDimension(600, 400)); - frame.setLocationRelativeTo(parent); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } - - public static void init(JFrame parent, JTextArea area, Callback callback) { - instance = new JavadocDialog(parent, area, callback); - instance.frame.doLayout(); - instance.frame.setVisible(true); - } - - public interface Callback { - void closeUi(JFrame frame, boolean save); - } - - private enum JavadocTag { - CODE(true), - LINK(true), - LINKPLAIN(true), - RETURN(false), - SEE(false), - THROWS(false); - - private boolean inline; - - private JavadocTag(boolean inline) { - this.inline = inline; - } - - public String getText() { - return "@" + this.name().toLowerCase(); - } - - public boolean isInline() { - return this.inline; - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java deleted file mode 100644 index e33ae82..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java +++ /dev/null @@ -1,109 +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.dialog; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; -import java.util.concurrent.CompletableFuture; - -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(String.format(I18n.translate("progress.operation"), Constants.NAME)); - 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 = Utils.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(ScaleUtil.getDimension(360, 50)); - - // show the frame - pane.doLayout(); - this.frame.setSize(ScaleUtil.getDimension(400, 120)); - this.frame.setResizable(false); - this.frame.setLocationRelativeTo(parent); - this.frame.setVisible(true); - this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - } - - public static CompletableFuture runOffThread(final JFrame parent, final ProgressRunnable runnable) { - CompletableFuture future = new CompletableFuture<>(); - new Thread(() -> - { - try (ProgressDialog progress = new ProgressDialog(parent)) { - runnable.run(progress); - future.complete(null); - } catch (Exception ex) { - future.completeExceptionally(ex); - throw new Error(ex); - } - }).start(); - return future; - } - - @Override - 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 step(int numDone, String message) { - this.labelText.setText(message); - if (numDone != -1) { - this.progress.setValue(numDone); - this.progress.setIndeterminate(false); - } else { - this.progress.setIndeterminate(true); - } - - // update the frame - this.frame.validate(); - this.frame.repaint(); - } - - public interface ProgressRunnable { - void run(ProgressListener listener) throws Exception; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java deleted file mode 100644 index b283a37..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java +++ /dev/null @@ -1,261 +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.dialog; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.event.*; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.gui.util.AbstractListCellRenderer; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.search.SearchEntry; -import cuchaz.enigma.utils.search.SearchUtil; - -public class SearchDialog { - - private final JTextField searchField; - private DefaultListModel classListModel; - private final JList classList; - private final JDialog dialog; - - private final Gui parent; - private final SearchUtil su; - private SearchUtil.SearchControl currentSearch; - - public SearchDialog(Gui parent) { - this.parent = parent; - - su = new SearchUtil<>(); - - dialog = new JDialog(parent.getFrame(), I18n.translate("menu.view.search"), true); - JPanel contentPane = new JPanel(); - contentPane.setBorder(ScaleUtil.createEmptyBorder(4, 4, 4, 4)); - contentPane.setLayout(new BorderLayout(ScaleUtil.scale(4), ScaleUtil.scale(4))); - - searchField = new JTextField(); - searchField.getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void insertUpdate(DocumentEvent e) { - updateList(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - updateList(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - updateList(); - } - - }); - searchField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_DOWN) { - int next = classList.isSelectionEmpty() ? 0 : classList.getSelectedIndex() + 1; - classList.setSelectedIndex(next); - classList.ensureIndexIsVisible(next); - } else if (e.getKeyCode() == KeyEvent.VK_UP) { - int prev = classList.isSelectionEmpty() ? classList.getModel().getSize() : classList.getSelectedIndex() - 1; - classList.setSelectedIndex(prev); - classList.ensureIndexIsVisible(prev); - } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - close(); - } - } - }); - searchField.addActionListener(e -> openSelected()); - contentPane.add(searchField, BorderLayout.NORTH); - - classListModel = new DefaultListModel<>(); - classList = new JList<>(); - classList.setModel(classListModel); - classList.setCellRenderer(new ListCellRendererImpl()); - classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - classList.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent mouseEvent) { - if (mouseEvent.getClickCount() >= 2) { - int idx = classList.locationToIndex(mouseEvent.getPoint()); - SearchEntryImpl entry = classList.getModel().getElementAt(idx); - openEntry(entry); - } - } - }); - contentPane.add(new JScrollPane(classList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); - - JPanel buttonBar = new JPanel(); - buttonBar.setLayout(new FlowLayout(FlowLayout.RIGHT)); - JButton open = new JButton(I18n.translate("prompt.open")); - open.addActionListener(event -> openSelected()); - buttonBar.add(open); - JButton cancel = new JButton(I18n.translate("prompt.cancel")); - cancel.addActionListener(event -> close()); - buttonBar.add(cancel); - contentPane.add(buttonBar, BorderLayout.SOUTH); - - // apparently the class list doesn't update by itself when the list - // state changes and the dialog is hidden - dialog.addComponentListener(new ComponentAdapter() { - @Override - public void componentShown(ComponentEvent e) { - classList.updateUI(); - } - }); - - dialog.setContentPane(contentPane); - dialog.setSize(ScaleUtil.getDimension(400, 500)); - dialog.setLocationRelativeTo(parent.getFrame()); - } - - public void show() { - su.clear(); - parent.getController().project.getJarIndex().getEntryIndex().getClasses().parallelStream() - .filter(e -> !e.isInnerClass()) - .map(e -> SearchEntryImpl.from(e, parent.getController())) - .map(SearchUtil.Entry::from) - .sequential() - .forEach(su::add); - - updateList(); - - searchField.requestFocus(); - searchField.selectAll(); - - dialog.setVisible(true); - } - - private void openSelected() { - SearchEntryImpl selectedValue = classList.getSelectedValue(); - if (selectedValue != null) { - openEntry(selectedValue); - } - } - - private void openEntry(SearchEntryImpl e) { - close(); - su.hit(e); - parent.getController().navigateTo(e.obf); - if (e.deobf != null) { - parent.getDeobfPanel().deobfClasses.setSelectionClass(e.deobf); - } else { - parent.getObfPanel().obfClasses.setSelectionClass(e.obf); - } - } - - private void close() { - dialog.setVisible(false); - } - - // Updates the list of class names - private void updateList() { - if (currentSearch != null) currentSearch.stop(); - - DefaultListModel classListModel = new DefaultListModel<>(); - this.classListModel = classListModel; - classList.setModel(classListModel); - - currentSearch = su.asyncSearch(searchField.getText(), (idx, e) -> SwingUtilities.invokeLater(() -> classListModel.insertElementAt(e, idx))); - } - - public void dispose() { - dialog.dispose(); - } - - private static final class SearchEntryImpl implements SearchEntry { - - public final ClassEntry obf; - public final ClassEntry deobf; - - private SearchEntryImpl(ClassEntry obf, ClassEntry deobf) { - this.obf = obf; - this.deobf = deobf; - } - - @Override - public List getSearchableNames() { - if (deobf != null) { - return Arrays.asList(obf.getSimpleName(), deobf.getSimpleName()); - } else { - return Collections.singletonList(obf.getSimpleName()); - } - } - - @Override - public String getIdentifier() { - return obf.getFullName(); - } - - @Override - public String toString() { - return String.format("SearchEntryImpl { obf: %s, deobf: %s }", obf, deobf); - } - - public static SearchEntryImpl from(ClassEntry e, GuiController controller) { - ClassEntry deobf = controller.project.getMapper().deobfuscate(e); - if (deobf.equals(e)) deobf = null; - return new SearchEntryImpl(e, deobf); - } - - } - - private static final class ListCellRendererImpl extends AbstractListCellRenderer { - - private final JLabel mainName; - private final JLabel secondaryName; - - public ListCellRendererImpl() { - this.setLayout(new BorderLayout()); - - mainName = new JLabel(); - this.add(mainName, BorderLayout.WEST); - - secondaryName = new JLabel(); - secondaryName.setFont(secondaryName.getFont().deriveFont(Font.ITALIC)); - secondaryName.setForeground(Color.GRAY); - this.add(secondaryName, BorderLayout.EAST); - } - - @Override - public void updateUiForEntry(JList list, SearchEntryImpl value, int index, boolean isSelected, boolean cellHasFocus) { - if (value.deobf == null) { - mainName.setText(value.obf.getSimpleName()); - mainName.setToolTipText(value.obf.getFullName()); - secondaryName.setText(""); - secondaryName.setToolTipText(""); - } else { - mainName.setText(value.deobf.getSimpleName()); - mainName.setToolTipText(value.deobf.getFullName()); - secondaryName.setText(value.obf.getSimpleName()); - secondaryName.setToolTipText(value.obf.getFullName()); - } - } - - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java deleted file mode 100644 index 868eba7..0000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java +++ /dev/null @@ -1,82 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import java.awt.BorderLayout; -import java.util.Arrays; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFrame; -import javax.swing.JPanel; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.stats.StatsMember; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.I18n; - -public class StatsDialog { - - public static void show(Gui gui) { - // init frame - JFrame frame = new JFrame(I18n.translate("menu.file.stats.title")); - JPanel checkboxesPanel = new JPanel(); - JPanel buttonPanel = new JPanel(); - frame.setLayout(new BorderLayout()); - frame.add(BorderLayout.NORTH, checkboxesPanel); - frame.add(BorderLayout.SOUTH, buttonPanel); - - // show checkboxes - Map checkboxes = Arrays - .stream(StatsMember.values()) - .collect(Collectors.toMap(m -> m, m -> { - JCheckBox checkbox = new JCheckBox(I18n.translate("type." + m.name().toLowerCase(Locale.ROOT))); - checkboxesPanel.add(checkbox); - return checkbox; - })); - - // show generate button - JButton button = new JButton(I18n.translate("menu.file.stats.generate")); - buttonPanel.add(button); - button.setEnabled(false); - button.addActionListener(action -> { - frame.dispose(); - generateStats(gui, checkboxes); - }); - - // add action listener to each checkbox - checkboxes.entrySet().forEach(checkbox -> { - checkbox.getValue().addActionListener(action -> { - if (!button.isEnabled()) { - button.setEnabled(true); - } else if (checkboxes.entrySet().stream().allMatch(entry -> !entry.getValue().isSelected())) { - button.setEnabled(false); - } - }); - }); - - // show the frame - frame.pack(); - frame.setVisible(true); - frame.setSize(ScaleUtil.getDimension(500, 120)); - frame.setResizable(false); - frame.setLocationRelativeTo(gui.getFrame()); - } - - private static void generateStats(Gui gui, Map checkboxes) { - // get members from selected checkboxes - Set includedMembers = checkboxes - .entrySet() - .stream() - .filter(entry -> entry.getValue().isSelected()) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); - - // checks if a projet is open - if (gui.getController().project != null) { - gui.getController().openStats(includedMembers); - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java b/src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java deleted file mode 100644 index fb497b1..0000000 --- a/src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import java.awt.event.MouseEvent; - -import javax.swing.JTabbedPane; - -public class CollapsibleTabbedPane extends JTabbedPane { - - public CollapsibleTabbedPane() { - } - - public CollapsibleTabbedPane(int tabPlacement) { - super(tabPlacement); - } - - public CollapsibleTabbedPane(int tabPlacement, int tabLayoutPolicy) { - super(tabPlacement, tabLayoutPolicy); - } - - @Override - protected void processMouseEvent(MouseEvent e) { - int id = e.getID(); - if (id == MouseEvent.MOUSE_PRESSED) { - if (!isEnabled()) return; - int tabIndex = getUI().tabForCoordinate(this, e.getX(), e.getY()); - if (tabIndex >= 0 && isEnabledAt(tabIndex)) { - if (tabIndex == getSelectedIndex()) { - if (isFocusOwner() && isRequestFocusEnabled()) { - requestFocus(); - } else { - setSelectedIndex(-1); - } - return; - } - } - } - super.processMouseEvent(e); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java deleted file mode 100644 index dc2cf8f..0000000 --- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ /dev/null @@ -1,386 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import cuchaz.enigma.config.Config; -import cuchaz.enigma.config.Themes; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.dialog.AboutDialog; -import cuchaz.enigma.gui.dialog.ChangeDialog; -import cuchaz.enigma.gui.dialog.ConnectToServerDialog; -import cuchaz.enigma.gui.dialog.CreateServerDialog; -import cuchaz.enigma.gui.dialog.StatsDialog; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Pair; - -import java.awt.Desktop; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import javax.swing.*; - -public class MenuBar extends JMenuBar { - - public final JMenuItem closeJarMenu; - public final List openMappingsMenus; - public final JMenuItem saveMappingsMenu; - public final List saveMappingsMenus; - public final JMenuItem closeMappingsMenu; - public final JMenuItem dropMappingsMenu; - public final JMenuItem exportSourceMenu; - public final JMenuItem exportJarMenu; - public final JMenuItem connectToServerMenu; - public final JMenuItem startServerMenu; - private final Gui gui; - - public MenuBar(Gui gui) { - this.gui = gui; - - /* - * File menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.file")); - this.add(menu); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.jar.open")); - menu.add(item); - item.addActionListener(event -> { - this.gui.jarFileChooser.setVisible(true); - String file = this.gui.jarFileChooser.getFile(); - // checks if the file name is not empty - if (file != null) { - Path path = Paths.get(this.gui.jarFileChooser.getDirectory()).resolve(file); - // checks if the file name corresponds to an existing file - if (Files.exists(path)) { - gui.getController().openJar(path); - } - } - }); - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.jar.close")); - menu.add(item); - item.addActionListener(event -> this.gui.getController().closeJar()); - this.closeJarMenu = item; - } - menu.addSeparator(); - JMenu openMenu = new JMenu(I18n.translate("menu.file.mappings.open")); - menu.add(openMenu); - { - openMappingsMenus = new ArrayList<>(); - for (MappingFormat format : MappingFormat.values()) { - if (format.getReader() != null) { - JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT))); - openMenu.add(item); - item.addActionListener(event -> { - if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { - File selectedFile = this.gui.enigmaMappingsFileChooser.getSelectedFile(); - this.gui.getController().openMappings(format, selectedFile.toPath()); - } - }); - openMappingsMenus.add(item); - } - } - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.mappings.save")); - menu.add(item); - item.addActionListener(event -> { - this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath()); - }); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); - this.saveMappingsMenu = item; - } - JMenu saveMenu = new JMenu(I18n.translate("menu.file.mappings.save_as")); - menu.add(saveMenu); - { - saveMappingsMenus = new ArrayList<>(); - for (MappingFormat format : MappingFormat.values()) { - if (format.getWriter() != null) { - JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT))); - saveMenu.add(item); - item.addActionListener(event -> { - // TODO: Use a specific file chooser for it - if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { - this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format); - this.saveMappingsMenu.setEnabled(true); - } - }); - saveMappingsMenus.add(item); - } - } - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.mappings.close")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.getController().isDirty()) { - this.gui.showDiscardDiag((response -> { - if (response == JOptionPane.YES_OPTION) { - gui.saveMapping(); - this.gui.getController().closeMappings(); - } else if (response == JOptionPane.NO_OPTION) - this.gui.getController().closeMappings(); - return null; - }), I18n.translate("prompt.close.save"), I18n.translate("prompt.close.discard"), I18n.translate("prompt.close.cancel")); - } else - this.gui.getController().closeMappings(); - - }); - this.closeMappingsMenu = item; - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.mappings.drop")); - menu.add(item); - item.addActionListener(event -> this.gui.getController().dropMappings()); - this.dropMappingsMenu = item; - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.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().toPath()); - } - }); - this.exportSourceMenu = item; - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.export.jar")); - menu.add(item); - item.addActionListener(event -> { - this.gui.exportJarFileChooser.setVisible(true); - if (this.gui.exportJarFileChooser.getFile() != null) { - Path path = Paths.get(this.gui.exportJarFileChooser.getDirectory(), this.gui.exportJarFileChooser.getFile()); - this.gui.getController().exportJar(path); - } - }); - this.exportJarMenu = item; - } - menu.addSeparator(); - { - JMenuItem stats = new JMenuItem(I18n.translate("menu.file.stats")); - menu.add(stats); - stats.addActionListener(event -> StatsDialog.show(this.gui)); - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.exit")); - menu.add(item); - item.addActionListener(event -> this.gui.close()); - } - } - - /* - * Decompiler menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.decompiler")); - this.add(menu); - - ButtonGroup decompilerGroup = new ButtonGroup(); - - for (Config.Decompiler decompiler : Config.Decompiler.values()) { - JRadioButtonMenuItem decompilerButton = new JRadioButtonMenuItem(decompiler.name); - decompilerGroup.add(decompilerButton); - if (decompiler.equals(Config.getInstance().decompiler)) { - decompilerButton.setSelected(true); - } - menu.add(decompilerButton); - decompilerButton.addActionListener(event -> { - gui.getController().setDecompiler(decompiler.service); - - try { - Config.getInstance().decompiler = decompiler; - Config.getInstance().saveConfig(); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } - } - - /* - * View menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.view")); - this.add(menu); - { - JMenu themes = new JMenu(I18n.translate("menu.view.themes")); - menu.add(themes); - ButtonGroup themeGroup = new ButtonGroup(); - for (Config.LookAndFeel lookAndFeel : Config.LookAndFeel.values()) { - JRadioButtonMenuItem themeButton = new JRadioButtonMenuItem(I18n.translate("menu.view.themes." + lookAndFeel.name().toLowerCase(Locale.ROOT))); - themeGroup.add(themeButton); - if (lookAndFeel.equals(Config.getInstance().lookAndFeel)) { - themeButton.setSelected(true); - } - themes.add(themeButton); - themeButton.addActionListener(event -> Themes.setLookAndFeel(gui, lookAndFeel)); - } - } - { - JMenu languages = new JMenu(I18n.translate("menu.view.languages")); - menu.add(languages); - ButtonGroup languageGroup = new ButtonGroup(); - for (String lang : I18n.getAvailableLanguages()) { - JRadioButtonMenuItem languageButton = new JRadioButtonMenuItem(I18n.getLanguageName(lang)); - languageGroup.add(languageButton); - if (lang.equals(Config.getInstance().language)) { - languageButton.setSelected(true); - } - languages.add(languageButton); - languageButton.addActionListener(event -> { - I18n.setLanguage(lang); - ChangeDialog.show(this.gui); - }); - } - } - { - JMenu scale = new JMenu(I18n.translate("menu.view.scale")); - { - ButtonGroup scaleGroup = new ButtonGroup(); - Map map = IntStream.of(100, 125, 150, 175, 200) - .mapToObj(scaleFactor -> { - float realScaleFactor = scaleFactor / 100f; - JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(String.format("%d%%", scaleFactor)); - menuItem.addActionListener(event -> ScaleUtil.setScaleFactor(realScaleFactor)); - menuItem.addActionListener(event -> ChangeDialog.show(this.gui)); - scaleGroup.add(menuItem); - scale.add(menuItem); - return new Pair<>(realScaleFactor, menuItem); - }) - .collect(Collectors.toMap(x -> x.a, x -> x.b)); - - JMenuItem customScale = new JMenuItem(I18n.translate("menu.view.scale.custom")); - customScale.addActionListener(event -> { - String answer = (String) JOptionPane.showInputDialog(gui.getFrame(), I18n.translate("menu.view.scale.custom.title"), I18n.translate("menu.view.scale.custom.title"), - JOptionPane.QUESTION_MESSAGE, null, null, Float.toString(ScaleUtil.getScaleFactor() * 100)); - if (answer == null) return; - float newScale = 1.0f; - try { - newScale = Float.parseFloat(answer) / 100f; - } catch (NumberFormatException ignored) { - } - ScaleUtil.setScaleFactor(newScale); - ChangeDialog.show(this.gui); - }); - scale.add(customScale); - ScaleUtil.addListener((newScale, _oldScale) -> { - JRadioButtonMenuItem mi = map.get(newScale); - if (mi != null) { - mi.setSelected(true); - } else { - scaleGroup.clearSelection(); - } - }); - JRadioButtonMenuItem mi = map.get(ScaleUtil.getScaleFactor()); - if (mi != null) { - mi.setSelected(true); - } - } - menu.add(scale); - } - menu.addSeparator(); - { - JMenuItem search = new JMenuItem(I18n.translate("menu.view.search")); - search.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_MASK)); - menu.add(search); - search.addActionListener(event -> { - if (this.gui.getController().project != null) { - this.gui.getSearchDialog().show(); - } - }); - } - } - - /* - * Collab menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.collab")); - this.add(menu); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.collab.connect")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.getController().getClient() != null) { - this.gui.getController().disconnectIfConnected(null); - return; - } - ConnectToServerDialog.Result result = ConnectToServerDialog.show(this.gui.getFrame()); - if (result == null) { - return; - } - this.gui.getController().disconnectIfConnected(null); - try { - this.gui.getController().createClient(result.getUsername(), result.getIp(), result.getPort(), result.getPassword()); - } catch (IOException e) { - JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.connect.error"), JOptionPane.ERROR_MESSAGE); - this.gui.getController().disconnectIfConnected(null); - } - Arrays.fill(result.getPassword(), (char)0); - }); - this.connectToServerMenu = item; - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.collab.server.start")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.getController().getServer() != null) { - this.gui.getController().disconnectIfConnected(null); - return; - } - CreateServerDialog.Result result = CreateServerDialog.show(this.gui.getFrame()); - if (result == null) { - return; - } - this.gui.getController().disconnectIfConnected(null); - try { - this.gui.getController().createServer(result.getPort(), result.getPassword()); - } catch (IOException e) { - JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.server.start.error"), JOptionPane.ERROR_MESSAGE); - this.gui.getController().disconnectIfConnected(null); - } - }); - this.startServerMenu = item; - } - } - - /* - * Help menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.help")); - this.add(menu); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.help.about")); - menu.add(item); - item.addActionListener(event -> AboutDialog.show(this.gui.getFrame())); - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.help.github")); - menu.add(item); - item.addActionListener(event -> { - try { - Desktop.getDesktop().browse(new URL("https://github.com/FabricMC/Enigma").toURI()); - } catch (URISyntaxException | IOException ignored) { - } - }); - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java deleted file mode 100644 index b92041c..0000000 --- a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java +++ /dev/null @@ -1,125 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -public class PopupMenuBar extends JPopupMenu { - - public final JMenuItem renameMenu; - public final JMenuItem editJavadocMenu; - public final JMenuItem showInheritanceMenu; - public final JMenuItem showImplementationsMenu; - public final JMenuItem showCallsMenu; - public final JMenuItem showCallsSpecificMenu; - public final JMenuItem openEntryMenu; - public final JMenuItem openPreviousMenu; - public final JMenuItem openNextMenu; - public final JMenuItem toggleMappingMenu; - - public PopupMenuBar(Gui gui) { - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.rename")); - menu.addActionListener(event -> gui.startRename()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.renameMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.javadoc")); - menu.addActionListener(event -> gui.startDocChange()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.editJavadocMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.inheritance")); - menu.addActionListener(event -> gui.showInheritance()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showInheritanceMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.implementations")); - menu.addActionListener(event -> gui.showImplementations()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showImplementationsMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.calls")); - menu.addActionListener(event -> gui.showCalls(true)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showCallsMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.calls.specific")); - menu.addActionListener(event -> gui.showCalls(false)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK + InputEvent.SHIFT_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showCallsSpecificMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.declaration")); - menu.addActionListener(event -> gui.getController().navigateTo(gui.cursorReference.entry)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.openEntryMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.back")); - menu.addActionListener(event -> gui.getController().openPreviousReference()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.openPreviousMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.forward")); - menu.addActionListener(event -> gui.getController().openNextReference()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.openNextMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.mark_deobfuscated")); - menu.addActionListener(event -> gui.toggleMapping()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.toggleMappingMenu = menu; - } - { - this.add(new JSeparator()); - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.zoom.in")); - menu.addActionListener(event -> gui.editor.offsetEditorZoom(2)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, InputEvent.CTRL_DOWN_MASK)); - this.add(menu); - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.zoom.out")); - menu.addActionListener(event -> gui.editor.offsetEditorZoom(-2)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK)); - this.add(menu); - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.zoom.reset")); - menu.addActionListener(event -> gui.editor.resetEditorZoom()); - this.add(menu); - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java deleted file mode 100644 index f5f6628..0000000 --- a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java +++ /dev/null @@ -1,10 +0,0 @@ -package cuchaz.enigma.gui.filechooser; - -import javax.swing.*; - -public class FileChooserAny extends JFileChooser { - public FileChooserAny() { - this.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - this.setAcceptAllFileFilterUsed(false); - } -} \ No newline at end of file diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java deleted file mode 100644 index cea11a6..0000000 --- a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java +++ /dev/null @@ -1,8 +0,0 @@ -package cuchaz.enigma.gui.filechooser; - -import javax.swing.*; - -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 deleted file mode 100644 index c16e0af..0000000 --- a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.gui.filechooser; - -import javax.swing.*; - -public class FileChooserFolder extends JFileChooser { - - public FileChooserFolder() { - this.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - this.setAcceptAllFileFilterUsed(false); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java deleted file mode 100644 index cef6494..0000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java +++ /dev/null @@ -1,69 +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.highlight; - -import cuchaz.enigma.config.Config; - -import javax.swing.text.BadLocationException; -import javax.swing.text.Highlighter; -import javax.swing.text.JTextComponent; -import java.awt.*; - -public class BoxHighlightPainter implements Highlighter.HighlightPainter { - private Color fillColor; - private Color borderColor; - - protected BoxHighlightPainter(Color fillColor, Color borderColor) { - this.fillColor = fillColor; - this.borderColor = borderColor; - } - - public static BoxHighlightPainter create(Config.AlphaColorEntry entry, Config.AlphaColorEntry entryOutline) { - return new BoxHighlightPainter(entry != null ? entry.get() : null, entryOutline != null ? entryOutline.get() : null); - } - - public static Rectangle getBounds(JTextComponent text, int start, int end) { - try { - // determine the bounds of the text - Rectangle startRect = text.modelToView(start); - Rectangle endRect = text.modelToView(end); - Rectangle bounds = startRect.union(endRect); - - // adjust the box so it looks nice - bounds.x -= 2; - bounds.width += 2; - bounds.y += 1; - bounds.height -= 2; - - return bounds; - } catch (BadLocationException ex) { - // don't care... just return something - return new Rectangle(0, 0, 0, 0); - } - } - - @Override - public void paint(Graphics g, int start, int end, Shape shape, JTextComponent text) { - Rectangle bounds = getBounds(text, start, end); - - // fill the area - if (this.fillColor != null) { - g.setColor(this.fillColor); - g.fillRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); - } - - // draw a box around the area - g.setColor(this.borderColor); - g.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java deleted file mode 100644 index 81a70a9..0000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java +++ /dev/null @@ -1,31 +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.highlight; - -import cuchaz.enigma.config.Config; - -import javax.swing.text.Highlighter; -import javax.swing.text.JTextComponent; -import java.awt.*; - -public class SelectionHighlightPainter implements Highlighter.HighlightPainter { - - @Override - public void paint(Graphics g, int start, int end, Shape shape, JTextComponent text) { - // draw a thick border - Graphics2D g2d = (Graphics2D) g; - Rectangle bounds = BoxHighlightPainter.getBounds(text, start, end); - g2d.setColor(new Color(Config.getInstance().selectionHighlightColor)); - g2d.setStroke(new BasicStroke(2.0f)); - g2d.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java b/src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java deleted file mode 100644 index ae23f32..0000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.gui.highlight; - -public enum TokenHighlightType { - OBFUSCATED, - DEOBFUSCATED, - PROPOSED -} diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java deleted file mode 100644 index 922f8f2..0000000 --- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java +++ /dev/null @@ -1,72 +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.node; - -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import javax.swing.tree.DefaultMutableTreeNode; - -public class ClassSelectorClassNode extends DefaultMutableTreeNode { - - private final ClassEntry obfEntry; - private ClassEntry classEntry; - - public ClassSelectorClassNode(ClassEntry obfEntry, ClassEntry classEntry) { - this.obfEntry = obfEntry; - this.classEntry = classEntry; - this.setUserObject(classEntry); - } - - public ClassEntry getObfEntry() { - return obfEntry; - } - - public ClassEntry getClassEntry() { - return this.classEntry; - } - - @Override - public String toString() { - return this.classEntry.getSimpleName(); - } - - @Override - public boolean equals(Object other) { - return other instanceof ClassSelectorClassNode && equals((ClassSelectorClassNode) other); - } - - @Override - public int hashCode() { - return 17 + (classEntry != null ? classEntry.hashCode() : 0); - } - - @Override - public Object getUserObject() { - return classEntry; - } - - @Override - public void setUserObject(Object userObject) { - String packageName = ""; - if (classEntry.getPackageName() != null) - packageName = classEntry.getPackageName() + "/"; - if (userObject instanceof String) - this.classEntry = new ClassEntry(packageName + userObject); - else if (userObject instanceof ClassEntry) - this.classEntry = (ClassEntry) userObject; - super.setUserObject(classEntry); - } - - public boolean equals(ClassSelectorClassNode other) { - return this.classEntry.equals(other.classEntry); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java deleted file mode 100644 index caa985c..0000000 --- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java +++ /dev/null @@ -1,58 +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.node; - -import javax.swing.tree.DefaultMutableTreeNode; - -public class ClassSelectorPackageNode extends DefaultMutableTreeNode { - - private String packageName; - - public ClassSelectorPackageNode(String packageName) { - this.packageName = packageName != null ? packageName : "(none)"; - } - - public String getPackageName() { - return packageName; - } - - @Override - public Object getUserObject() { - return packageName; - } - - @Override - public void setUserObject(Object userObject) { - if (userObject instanceof String) - this.packageName = (String) userObject; - super.setUserObject(userObject); - } - - @Override - public String toString() { - return !packageName.equals("(none)") ? this.packageName : "(none)"; - } - - @Override - public boolean equals(Object other) { - return other instanceof ClassSelectorPackageNode && equals((ClassSelectorPackageNode) other); - } - - @Override - public int hashCode() { - return packageName.hashCode(); - } - - public boolean equals(ClassSelectorPackageNode other) { - return other != null && this.packageName.equals(other.packageName); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java b/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java deleted file mode 100644 index c24226b..0000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java +++ /dev/null @@ -1,26 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.gui.ClassSelector; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.*; - -public class PanelDeobf extends JPanel { - - public final ClassSelector deobfClasses; - private final Gui gui; - - public PanelDeobf(Gui gui) { - this.gui = gui; - - this.deobfClasses = new ClassSelector(gui, ClassSelector.DEOBF_CLASS_COMPARATOR, true); - this.deobfClasses.setSelectionListener(gui.getController()::navigateTo); - this.deobfClasses.setRenameSelectionListener(gui::onPanelRename); - - this.setLayout(new BorderLayout()); - this.add(new JLabel(I18n.translate("info_panel.classes.deobfuscated")), 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 deleted file mode 100644 index 8637afd..0000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java +++ /dev/null @@ -1,171 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.gui.BrowserCaret; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.gui.util.ScaleUtil; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -public class PanelEditor extends JEditorPane { - private boolean mouseIsPressed = false; - public int fontSize = 12; - - public PanelEditor(Gui gui) { - this.setEditable(false); - this.setSelectionColor(new Color(31, 46, 90)); - this.setCaret(new BrowserCaret()); - this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); - this.addCaretListener(event -> gui.onCaretMove(event.getDot(), mouseIsPressed)); - final PanelEditor self = this; - this.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent mouseEvent) { - mouseIsPressed = true; - } - - @Override - public void mouseReleased(MouseEvent e) { - switch (e.getButton()) { - case MouseEvent.BUTTON3: // Right click - self.setCaretPosition(self.viewToModel(e.getPoint())); - break; - - case 4: // Back navigation - gui.getController().openPreviousReference(); - break; - - case 5: // Forward navigation - gui.getController().openNextReference(); - break; - } - mouseIsPressed = false; - } - }); - this.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - if (event.isControlDown()) { - gui.setShouldNavigateOnClick(false); - switch (event.getKeyCode()) { - 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_E: - gui.popupMenu.openNextMenu.doClick(); - break; - - case KeyEvent.VK_C: - if (event.isShiftDown()) { - gui.popupMenu.showCallsSpecificMenu.doClick(); - } else { - gui.popupMenu.showCallsMenu.doClick(); - } - break; - - case KeyEvent.VK_O: - gui.popupMenu.toggleMappingMenu.doClick(); - break; - - case KeyEvent.VK_R: - gui.popupMenu.renameMenu.doClick(); - break; - - case KeyEvent.VK_D: - gui.popupMenu.editJavadocMenu.doClick(); - break; - - case KeyEvent.VK_F5: - gui.getController().refreshCurrentClass(); - break; - - case KeyEvent.VK_F: - // prevent navigating on click when quick find activated - break; - - case KeyEvent.VK_ADD: - case KeyEvent.VK_EQUALS: - case KeyEvent.VK_PLUS: - self.offsetEditorZoom(2); - break; - case KeyEvent.VK_SUBTRACT: - case KeyEvent.VK_MINUS: - self.offsetEditorZoom(-2); - break; - - default: - gui.setShouldNavigateOnClick(true); // CTRL - break; - } - } - } - - @Override - public void keyTyped(KeyEvent event) { - if (!gui.popupMenu.renameMenu.isEnabled()) return; - - if (!event.isControlDown() && !event.isAltDown() && Character.isJavaIdentifierPart(event.getKeyChar())) { - EnigmaProject project = gui.getController().project; - EntryReference, Entry> reference = project.getMapper().deobfuscate(gui.cursorReference); - Entry entry = reference.getNameableEntry(); - - String name = String.valueOf(event.getKeyChar()); - if (entry instanceof ClassEntry && ((ClassEntry) entry).getParent() == null) { - String packageName = ((ClassEntry) entry).getPackageName(); - if (packageName != null) { - name = packageName + "/" + name; - } - } - - gui.popupMenu.renameMenu.doClick(); - gui.renameTextField.setText(name); - } - } - - @Override - public void keyReleased(KeyEvent event) { - gui.setShouldNavigateOnClick(event.isControlDown()); - } - }); - } - - public void offsetEditorZoom(int zoomAmount) { - int newResult = this.fontSize + zoomAmount; - if (newResult > 8 && newResult < 72) { - this.fontSize = newResult; - this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); - } - } - - public void resetEditorZoom() { - this.fontSize = 12; - this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); - } - - @Override - public Color getCaretColor() { - return new Color(Config.getInstance().caretColor); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java b/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java deleted file mode 100644 index de069bc..0000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java +++ /dev/null @@ -1,32 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; - -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(ScaleUtil.getDimension(0, 100)); - this.setBorder(BorderFactory.createTitledBorder(I18n.translate("info_panel.identifier"))); - } - - public void clearReference() { - this.removeAll(); - JLabel label = new JLabel(I18n.translate("info_panel.identifier.none")); - Utils.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 deleted file mode 100644 index dd7f9f9..0000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java +++ /dev/null @@ -1,37 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.gui.ClassSelector; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.*; -import java.util.Comparator; - -public class PanelObf extends JPanel { - - public final ClassSelector obfClasses; - private final Gui gui; - - public PanelObf(Gui gui) { - this.gui = gui; - - Comparator obfClassComparator = (a, b) -> { - String aname = a.getFullName(); - String bname = b.getFullName(); - if (aname.length() != bname.length()) { - return aname.length() - bname.length(); - } - return aname.compareTo(bname); - }; - - this.obfClasses = new ClassSelector(gui, obfClassComparator, false); - this.obfClasses.setSelectionListener(gui.getController()::navigateTo); - this.obfClasses.setRenameSelectionListener(gui::onPanelRename); - - this.setLayout(new BorderLayout()); - this.add(new JLabel(I18n.translate("info_panel.classes.obfuscated")), BorderLayout.NORTH); - this.add(new JScrollPane(this.obfClasses), BorderLayout.CENTER); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java b/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java deleted file mode 100644 index e783530..0000000 --- a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java +++ /dev/null @@ -1,197 +0,0 @@ -package cuchaz.enigma.gui.stats; - -import com.google.gson.GsonBuilder; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.api.service.ObfuscationTestService; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.I18n; - -import java.util.*; - -public class StatsGenerator { - private final EntryIndex entryIndex; - private final EntryRemapper mapper; - private final EntryResolver entryResolver; - private final List obfuscationTestServices; - private final List nameProposalServices; - - public StatsGenerator(EnigmaProject project) { - entryIndex = project.getJarIndex().getEntryIndex(); - mapper = project.getMapper(); - entryResolver = project.getJarIndex().getEntryResolver(); - obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE); - nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE); - } - - public String generate(ProgressListener progress, Set includedMembers) { - includedMembers = EnumSet.copyOf(includedMembers); - int totalWork = 0; - - if (includedMembers.contains(StatsMember.METHODS) || includedMembers.contains(StatsMember.PARAMETERS)) { - totalWork += entryIndex.getMethods().size(); - } - - if (includedMembers.contains(StatsMember.FIELDS)) { - totalWork += entryIndex.getFields().size(); - } - - if (includedMembers.contains(StatsMember.CLASSES)) { - totalWork += entryIndex.getClasses().size(); - } - - progress.init(totalWork, I18n.translate("progress.stats")); - - Map counts = new HashMap<>(); - - int numDone = 0; - if (includedMembers.contains(StatsMember.METHODS) || includedMembers.contains(StatsMember.PARAMETERS)) { - for (MethodEntry method : entryIndex.getMethods()) { - progress.step(numDone++, I18n.translate("type.methods")); - MethodEntry root = entryResolver - .resolveEntry(method, ResolutionStrategy.RESOLVE_ROOT) - .stream() - .findFirst() - .orElseThrow(AssertionError::new); - - if (root == method && !((MethodDefEntry) method).getAccess().isSynthetic()) { - if (includedMembers.contains(StatsMember.METHODS)) { - update(counts, method); - } - - if (includedMembers.contains(StatsMember.PARAMETERS)) { - int index = ((MethodDefEntry) method).getAccess().isStatic() ? 0 : 1; - for (TypeDescriptor argument : method.getDesc().getArgumentDescs()) { - update(counts, new LocalVariableEntry(method, index, "", true,null)); - index += argument.getSize(); - } - } - } - } - } - - if (includedMembers.contains(StatsMember.FIELDS)) { - for (FieldEntry field : entryIndex.getFields()) { - progress.step(numDone++, I18n.translate("type.fields")); - update(counts, field); - } - } - - if (includedMembers.contains(StatsMember.CLASSES)) { - for (ClassEntry clazz : entryIndex.getClasses()) { - progress.step(numDone++, I18n.translate("type.classes")); - update(counts, clazz); - } - } - - progress.step(-1, I18n.translate("progress.stats.data")); - - Tree tree = new Tree<>(); - - for (Map.Entry entry : counts.entrySet()) { - if (entry.getKey().startsWith("com.mojang")) continue; // just a few unmapped names, no point in having a subsection - tree.getNode(entry.getKey()).value = entry.getValue(); - } - - tree.collapse(tree.root); - return new GsonBuilder().setPrettyPrinting().create().toJson(tree.root); - } - - private void update(Map counts, Entry entry) { - if (isObfuscated(entry)) { - String parent = mapper.deobfuscate(entry.getAncestry().get(0)).getName().replace('/', '.'); - counts.put(parent, counts.getOrDefault(parent, 0) + 1); - } - } - - private boolean isObfuscated(Entry entry) { - String name = entry.getName(); - - if (!obfuscationTestServices.isEmpty()) { - for (ObfuscationTestService service : obfuscationTestServices) { - if (service.testDeobfuscated(entry)) { - return false; - } - } - } - - if (!nameProposalServices.isEmpty()) { - for (NameProposalService service : nameProposalServices) { - if (service.proposeName(entry, mapper).isPresent()) { - return false; - } - } - } - - String mappedName = mapper.deobfuscate(entry).getName(); - if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) { - return false; - } - - return true; - } - - private static class Tree { - public final Node root; - private final Map> nodes = new HashMap<>(); - - public static class Node { - public String name; - public T value; - public List> children = new ArrayList<>(); - private final transient Map> namedChildren = new HashMap<>(); - - public Node(String name, T value) { - this.name = name; - this.value = value; - } - } - - public Tree() { - root = new Node<>("", null); - } - - public Node getNode(String name) { - Node node = nodes.get(name); - - if (node == null) { - node = root; - - for (String part : name.split("\\.")) { - Node child = node.namedChildren.get(part); - - if (child == null) { - child = new Node<>(part, null); - node.namedChildren.put(part, child); - node.children.add(child); - } - - node = child; - } - - nodes.put(name, node); - } - - return node; - } - - public void collapse(Node node) { - while (node.children.size() == 1) { - Node child = node.children.get(0); - node.name = node.name.isEmpty() ? child.name : node.name + "." + child.name; - node.children = child.children; - node.value = child.value; - } - - for (Node child : node.children) { - collapse(child); - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java b/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java deleted file mode 100644 index 70b4f40..0000000 --- a/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java +++ /dev/null @@ -1,8 +0,0 @@ -package cuchaz.enigma.gui.stats; - -public enum StatsMember { - METHODS, - FIELDS, - PARAMETERS, - CLASSES -} diff --git a/src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java b/src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java deleted file mode 100644 index 612e3e9..0000000 --- a/src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java +++ /dev/null @@ -1,77 +0,0 @@ -package cuchaz.enigma.gui.util; - -import java.awt.Component; -import java.awt.event.MouseEvent; - -import javax.swing.*; -import javax.swing.border.Border; - -public abstract class AbstractListCellRenderer extends JPanel implements ListCellRenderer { - - private static final Border NO_FOCUS_BORDER = BorderFactory.createEmptyBorder(1, 1, 1, 1); - - private Border noFocusBorder; - - public AbstractListCellRenderer() { - setBorder(getNoFocusBorder()); - } - - protected Border getNoFocusBorder() { - if (noFocusBorder == null) { - Border border = UIManager.getLookAndFeel().getDefaults().getBorder("List.List.cellNoFocusBorder"); - noFocusBorder = border != null ? border : NO_FOCUS_BORDER; - } - return noFocusBorder; - } - - protected Border getBorder(boolean isSelected, boolean cellHasFocus) { - Border b = null; - if (cellHasFocus) { - UIDefaults defaults = UIManager.getLookAndFeel().getDefaults(); - if (isSelected) { - b = defaults.getBorder("List.focusSelectedCellHighlightBorder"); - } - if (b == null) { - b = defaults.getBorder("List.focusCellHighlightBorder"); - } - } else { - b = getNoFocusBorder(); - } - return b; - } - - public abstract void updateUiForEntry(JList list, E value, int index, boolean isSelected, boolean cellHasFocus); - - @Override - public Component getListCellRendererComponent(JList list, E value, int index, boolean isSelected, boolean cellHasFocus) { - updateUiForEntry(list, value, index, isSelected, cellHasFocus); - - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - setEnabled(list.isEnabled()); - setFont(list.getFont()); - - setBorder(getBorder(isSelected, cellHasFocus)); - - // This isn't the width of the cell, but it's close enough for where it's needed (getComponentAt in getToolTipText) - setSize(list.getWidth(), getPreferredSize().height); - - return this; - } - - @Override - public String getToolTipText(MouseEvent event) { - Component c = getComponentAt(event.getPoint()); - if (c instanceof JComponent) { - return ((JComponent) c).getToolTipText(); - } - return getToolTipText(); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/util/History.java b/src/main/java/cuchaz/enigma/gui/util/History.java deleted file mode 100644 index 94f3105..0000000 --- a/src/main/java/cuchaz/enigma/gui/util/History.java +++ /dev/null @@ -1,49 +0,0 @@ -package cuchaz.enigma.gui.util; - -import com.google.common.collect.Queues; - -import java.util.Deque; - -public class History { - private final Deque previous = Queues.newArrayDeque(); - private final Deque next = Queues.newArrayDeque(); - private T current; - - public History(T initial) { - current = initial; - } - - public T getCurrent() { - return current; - } - - public void push(T value) { - previous.addLast(current); - current = value; - next.clear(); - } - - public void replace(T value) { - current = value; - } - - public boolean canGoBack() { - return !previous.isEmpty(); - } - - public T goBack() { - next.addFirst(current); - current = previous.removeLast(); - return current; - } - - public boolean canGoForward() { - return !next.isEmpty(); - } - - public T goForward() { - previous.addLast(current); - current = next.removeFirst(); - return current; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java b/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java deleted file mode 100644 index d045c6d..0000000 --- a/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package cuchaz.enigma.gui.util; - -@FunctionalInterface -public interface ScaleChangeListener { - - void onScaleChanged(float scale, float oldScale); - -} diff --git a/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java b/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java deleted file mode 100644 index 9f722e9..0000000 --- a/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -package cuchaz.enigma.gui.util; - -import java.awt.Dimension; -import java.awt.Font; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.UIManager; -import javax.swing.border.Border; - -import com.github.swingdpi.UiDefaultsScaler; -import com.github.swingdpi.plaf.BasicTweaker; -import com.github.swingdpi.plaf.MetalTweaker; -import com.github.swingdpi.plaf.NimbusTweaker; -import com.github.swingdpi.plaf.WindowsTweaker; -import cuchaz.enigma.config.Config; -import de.sciss.syntaxpane.DefaultSyntaxKit; - -public class ScaleUtil { - - private static List listeners = new ArrayList<>(); - - public static float getScaleFactor() { - return Config.getInstance().scaleFactor; - } - - public static void setScaleFactor(float scaleFactor) { - float oldScale = getScaleFactor(); - float clamped = Math.min(Math.max(0.25f, scaleFactor), 10.0f); - Config.getInstance().scaleFactor = clamped; - try { - Config.getInstance().saveConfig(); - } catch (IOException e) { - e.printStackTrace(); - } - listeners.forEach(l -> l.onScaleChanged(clamped, oldScale)); - } - - public static void addListener(ScaleChangeListener listener) { - listeners.add(listener); - } - - public static void removeListener(ScaleChangeListener listener) { - listeners.remove(listener); - } - - public static Dimension getDimension(int width, int height) { - return new Dimension(scale(width), scale(height)); - } - - public static Font getFont(String fontName, int plain, int fontSize) { - return scaleFont(new Font(fontName, plain, fontSize)); - } - - public static Font scaleFont(Font font) { - return createTweakerForCurrentLook(getScaleFactor()).modifyFont("", font); - } - - public static float scale(float f) { - return f * getScaleFactor(); - } - - public static float invert(float f) { - return f / getScaleFactor(); - } - - public static int scale(int i) { - return (int) (i * getScaleFactor()); - } - - public static Border createEmptyBorder(int top, int left, int bottom, int right) { - return BorderFactory.createEmptyBorder(scale(top), scale(left), scale(bottom), scale(right)); - } - - public static int invert(int i) { - return (int) (i / getScaleFactor()); - } - - public static void applyScaling() { - float scale = getScaleFactor(); - UiDefaultsScaler.updateAndApplyGlobalScaling((int) (100 * scale), true); - try { - Field defaultFontField = DefaultSyntaxKit.class.getDeclaredField("DEFAULT_FONT"); - defaultFontField.setAccessible(true); - Font font = (Font) defaultFontField.get(null); - font = font.deriveFont(12 * scale); - defaultFontField.set(null, font); - } catch (NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - } - - private static BasicTweaker createTweakerForCurrentLook(float dpiScaling) { - String testString = UIManager.getLookAndFeel().getName().toLowerCase(); - if (testString.contains("windows")) { - return new WindowsTweaker(dpiScaling, testString.contains("classic")); - } - if (testString.contains("metal")) { - return new MetalTweaker(dpiScaling); - } - if (testString.contains("nimbus")) { - return new NimbusTweaker(dpiScaling); - } - return new BasicTweaker(dpiScaling); - } - -} -- cgit v1.2.3