diff options
Diffstat (limited to 'enigma-swing/src/main/java')
6 files changed, 194 insertions, 66 deletions
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java index 488d04ed..b27832be 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java | |||
| @@ -27,6 +27,7 @@ import com.google.common.collect.Maps; | |||
| 27 | import com.google.common.collect.Multimap; | 27 | import com.google.common.collect.Multimap; |
| 28 | import cuchaz.enigma.gui.node.ClassSelectorClassNode; | 28 | import cuchaz.enigma.gui.node.ClassSelectorClassNode; |
| 29 | import cuchaz.enigma.gui.node.ClassSelectorPackageNode; | 29 | import cuchaz.enigma.gui.node.ClassSelectorPackageNode; |
| 30 | import cuchaz.enigma.gui.util.GuiUtil; | ||
| 30 | import cuchaz.enigma.translation.Translator; | 31 | import cuchaz.enigma.translation.Translator; |
| 31 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 32 | import cuchaz.enigma.translation.representation.entry.ClassEntry; |
| 32 | import cuchaz.enigma.utils.validation.ValidationContext; | 33 | import cuchaz.enigma.utils.validation.ValidationContext; |
| @@ -69,10 +70,13 @@ public class ClassSelector extends JTree { | |||
| 69 | } | 70 | } |
| 70 | }); | 71 | }); |
| 71 | 72 | ||
| 73 | final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); | ||
| 74 | renderer.setLeafIcon(GuiUtil.CLASS_ICON); | ||
| 75 | setCellRenderer(renderer); | ||
| 76 | |||
| 72 | final JTree tree = this; | 77 | final JTree tree = this; |
| 73 | 78 | ||
| 74 | final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, | 79 | final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, renderer) { |
| 75 | (DefaultTreeCellRenderer) tree.getCellRenderer()) { | ||
| 76 | @Override | 80 | @Override |
| 77 | public boolean isCellEditable(EventObject event) { | 81 | public boolean isCellEditable(EventObject event) { |
| 78 | return isRenamable && !(event instanceof MouseEvent) && super.isCellEditable(event); | 82 | return isRenamable && !(event instanceof MouseEvent) && super.isCellEditable(event); |
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java index c56731dc..d74fefd9 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java | |||
| @@ -51,10 +51,7 @@ import cuchaz.enigma.network.packet.RemoveMappingC2SPacket; | |||
| 51 | import cuchaz.enigma.network.packet.RenameC2SPacket; | 51 | import cuchaz.enigma.network.packet.RenameC2SPacket; |
| 52 | import cuchaz.enigma.source.Token; | 52 | import cuchaz.enigma.source.Token; |
| 53 | import cuchaz.enigma.translation.mapping.EntryRemapper; | 53 | import cuchaz.enigma.translation.mapping.EntryRemapper; |
| 54 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 54 | import cuchaz.enigma.translation.representation.entry.*; |
| 55 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 56 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 57 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 58 | import cuchaz.enigma.utils.I18n; | 55 | import cuchaz.enigma.utils.I18n; |
| 59 | import cuchaz.enigma.utils.validation.ParameterizedMessage; | 56 | import cuchaz.enigma.utils.validation.ParameterizedMessage; |
| 60 | import cuchaz.enigma.utils.validation.ValidationContext; | 57 | import cuchaz.enigma.utils.validation.ValidationContext; |
| @@ -82,6 +79,7 @@ public class Gui implements LanguageChangeListener { | |||
| 82 | private JPanel classesPanel; | 79 | private JPanel classesPanel; |
| 83 | private JSplitPane splitClasses; | 80 | private JSplitPane splitClasses; |
| 84 | private IdentifierPanel infoPanel; | 81 | private IdentifierPanel infoPanel; |
| 82 | private StructurePanel structurePanel; | ||
| 85 | private JTree inheritanceTree; | 83 | private JTree inheritanceTree; |
| 86 | private JTree implementationsTree; | 84 | private JTree implementationsTree; |
| 87 | private JTree callsTree; | 85 | private JTree callsTree; |
| @@ -163,13 +161,17 @@ public class Gui implements LanguageChangeListener { | |||
| 163 | // init info panel | 161 | // init info panel |
| 164 | infoPanel = new IdentifierPanel(this); | 162 | infoPanel = new IdentifierPanel(this); |
| 165 | 163 | ||
| 164 | // init structure panel | ||
| 165 | this.structurePanel = new StructurePanel(this); | ||
| 166 | |||
| 166 | // init inheritance panel | 167 | // init inheritance panel |
| 167 | inheritanceTree = new JTree(); | 168 | inheritanceTree = new JTree(); |
| 168 | inheritanceTree.setModel(null); | 169 | inheritanceTree.setModel(null); |
| 170 | inheritanceTree.setShowsRootHandles(true); | ||
| 169 | inheritanceTree.addMouseListener(new MouseAdapter() { | 171 | inheritanceTree.addMouseListener(new MouseAdapter() { |
| 170 | @Override | 172 | @Override |
| 171 | public void mouseClicked(MouseEvent event) { | 173 | public void mouseClicked(MouseEvent event) { |
| 172 | if (event.getClickCount() >= 2) { | 174 | if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { |
| 173 | // get the selected node | 175 | // get the selected node |
| 174 | TreePath path = inheritanceTree.getSelectionPath(); | 176 | TreePath path = inheritanceTree.getSelectionPath(); |
| 175 | if (path == null) { | 177 | if (path == null) { |
| @@ -199,10 +201,11 @@ public class Gui implements LanguageChangeListener { | |||
| 199 | // init implementations panel | 201 | // init implementations panel |
| 200 | implementationsTree = new JTree(); | 202 | implementationsTree = new JTree(); |
| 201 | implementationsTree.setModel(null); | 203 | implementationsTree.setModel(null); |
| 204 | implementationsTree.setShowsRootHandles(true); | ||
| 202 | implementationsTree.addMouseListener(new MouseAdapter() { | 205 | implementationsTree.addMouseListener(new MouseAdapter() { |
| 203 | @Override | 206 | @Override |
| 204 | public void mouseClicked(MouseEvent event) { | 207 | public void mouseClicked(MouseEvent event) { |
| 205 | if (event.getClickCount() >= 2) { | 208 | if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { |
| 206 | // get the selected node | 209 | // get the selected node |
| 207 | TreePath path = implementationsTree.getSelectionPath(); | 210 | TreePath path = implementationsTree.getSelectionPath(); |
| 208 | if (path == null) { | 211 | if (path == null) { |
| @@ -227,11 +230,12 @@ public class Gui implements LanguageChangeListener { | |||
| 227 | // init call panel | 230 | // init call panel |
| 228 | callsTree = new JTree(); | 231 | callsTree = new JTree(); |
| 229 | callsTree.setModel(null); | 232 | callsTree.setModel(null); |
| 233 | callsTree.setShowsRootHandles(true); | ||
| 230 | callsTree.addMouseListener(new MouseAdapter() { | 234 | callsTree.addMouseListener(new MouseAdapter() { |
| 231 | @SuppressWarnings("unchecked") | 235 | @SuppressWarnings("unchecked") |
| 232 | @Override | 236 | @Override |
| 233 | public void mouseClicked(MouseEvent event) { | 237 | public void mouseClicked(MouseEvent event) { |
| 234 | if (event.getClickCount() >= 2) { | 238 | if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { |
| 235 | // get the selected node | 239 | // get the selected node |
| 236 | TreePath path = callsTree.getSelectionPath(); | 240 | TreePath path = callsTree.getSelectionPath(); |
| 237 | if (path == null) { | 241 | if (path == null) { |
| @@ -287,6 +291,8 @@ public class Gui implements LanguageChangeListener { | |||
| 287 | editorTabPopupMenu.show(openFiles, e.getX(), e.getY(), EditorPanel.byUi(openFiles.getComponentAt(i))); | 291 | editorTabPopupMenu.show(openFiles, e.getX(), e.getY(), EditorPanel.byUi(openFiles.getComponentAt(i))); |
| 288 | } | 292 | } |
| 289 | } | 293 | } |
| 294 | |||
| 295 | showStructure(getActiveEditor()); | ||
| 290 | } | 296 | } |
| 291 | }); | 297 | }); |
| 292 | 298 | ||
| @@ -311,6 +317,7 @@ public class Gui implements LanguageChangeListener { | |||
| 311 | centerPanel.add(openFiles, BorderLayout.CENTER); | 317 | centerPanel.add(openFiles, BorderLayout.CENTER); |
| 312 | tabs = new JTabbedPane(); | 318 | tabs = new JTabbedPane(); |
| 313 | tabs.setPreferredSize(ScaleUtil.getDimension(250, 0)); | 319 | tabs.setPreferredSize(ScaleUtil.getDimension(250, 0)); |
| 320 | tabs.addTab(I18n.translate("info_panel.tree.structure"), structurePanel); | ||
| 314 | tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel); | 321 | tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel); |
| 315 | tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel); | 322 | tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel); |
| 316 | tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel); | 323 | tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel); |
| @@ -482,11 +489,14 @@ public class Gui implements LanguageChangeListener { | |||
| 482 | } | 489 | } |
| 483 | }); | 490 | }); |
| 484 | 491 | ||
| 492 | showStructure(ed); | ||
| 493 | |||
| 485 | return ed; | 494 | return ed; |
| 486 | }); | 495 | }); |
| 487 | if (editorPanel != null) { | 496 | if (editorPanel != null) { |
| 488 | openFiles.setSelectedComponent(editors.get(entry).getUi()); | 497 | openFiles.setSelectedComponent(editors.get(entry).getUi()); |
| 489 | } | 498 | } |
| 499 | |||
| 490 | return editorPanel; | 500 | return editorPanel; |
| 491 | } | 501 | } |
| 492 | 502 | ||
| @@ -506,6 +516,7 @@ public class Gui implements LanguageChangeListener { | |||
| 506 | public void closeEditor(EditorPanel ed) { | 516 | public void closeEditor(EditorPanel ed) { |
| 507 | openFiles.remove(ed.getUi()); | 517 | openFiles.remove(ed.getUi()); |
| 508 | editors.inverse().remove(ed); | 518 | editors.inverse().remove(ed); |
| 519 | showStructure(getActiveEditor()); | ||
| 509 | ed.destroy(); | 520 | ed.destroy(); |
| 510 | } | 521 | } |
| 511 | 522 | ||
| @@ -595,6 +606,32 @@ public class Gui implements LanguageChangeListener { | |||
| 595 | infoPanel.startRenaming(); | 606 | infoPanel.startRenaming(); |
| 596 | } | 607 | } |
| 597 | 608 | ||
| 609 | public void showStructure(EditorPanel editor) { | ||
| 610 | JTree structureTree = this.structurePanel.getStructureTree(); | ||
| 611 | structureTree.setModel(null); | ||
| 612 | |||
| 613 | if (editor == null) { | ||
| 614 | this.structurePanel.getSortingPanel().setVisible(false); | ||
| 615 | return; | ||
| 616 | } | ||
| 617 | |||
| 618 | ClassEntry classEntry = editor.getClassHandle().getRef(); | ||
| 619 | if (classEntry == null) return; | ||
| 620 | |||
| 621 | this.structurePanel.getSortingPanel().setVisible(true); | ||
| 622 | |||
| 623 | // get the class structure | ||
| 624 | StructureTreeNode node = this.controller.getClassStructure(classEntry, this.structurePanel.shouldHideDeobfuscated()); | ||
| 625 | |||
| 626 | // show the tree at the root | ||
| 627 | TreePath path = getPathToRoot(node); | ||
| 628 | structureTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); | ||
| 629 | structureTree.expandPath(path); | ||
| 630 | structureTree.setSelectionRow(structureTree.getRowForPath(path)); | ||
| 631 | |||
| 632 | redraw(); | ||
| 633 | } | ||
| 634 | |||
| 598 | public void showInheritance(EditorPanel editor) { | 635 | public void showInheritance(EditorPanel editor) { |
| 599 | EntryReference<Entry<?>, Entry<?>> cursorReference = editor.getCursorReference(); | 636 | EntryReference<Entry<?>, Entry<?>> cursorReference = editor.getCursorReference(); |
| 600 | if (cursorReference == null) return; | 637 | if (cursorReference == null) return; |
| @@ -621,7 +658,7 @@ public class Gui implements LanguageChangeListener { | |||
| 621 | inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); | 658 | inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); |
| 622 | } | 659 | } |
| 623 | 660 | ||
| 624 | tabs.setSelectedIndex(0); | 661 | tabs.setSelectedIndex(1); |
| 625 | 662 | ||
| 626 | redraw(); | 663 | redraw(); |
| 627 | } | 664 | } |
| @@ -649,7 +686,7 @@ public class Gui implements LanguageChangeListener { | |||
| 649 | implementationsTree.setSelectionRow(implementationsTree.getRowForPath(path)); | 686 | implementationsTree.setSelectionRow(implementationsTree.getRowForPath(path)); |
| 650 | } | 687 | } |
| 651 | 688 | ||
| 652 | tabs.setSelectedIndex(1); | 689 | tabs.setSelectedIndex(2); |
| 653 | 690 | ||
| 654 | redraw(); | 691 | redraw(); |
| 655 | } | 692 | } |
| @@ -669,7 +706,7 @@ public class Gui implements LanguageChangeListener { | |||
| 669 | callsTree.setModel(new DefaultTreeModel(node)); | 706 | callsTree.setModel(new DefaultTreeModel(node)); |
| 670 | } | 707 | } |
| 671 | 708 | ||
| 672 | tabs.setSelectedIndex(2); | 709 | tabs.setSelectedIndex(3); |
| 673 | 710 | ||
| 674 | redraw(); | 711 | redraw(); |
| 675 | } | 712 | } |
| @@ -893,9 +930,10 @@ public class Gui implements LanguageChangeListener { | |||
| 893 | public void retranslateUi() { | 930 | public void retranslateUi() { |
| 894 | this.jarFileChooser.setTitle(I18n.translate("menu.file.jar.open")); | 931 | this.jarFileChooser.setTitle(I18n.translate("menu.file.jar.open")); |
| 895 | this.exportJarFileChooser.setTitle(I18n.translate("menu.file.export.jar")); | 932 | this.exportJarFileChooser.setTitle(I18n.translate("menu.file.export.jar")); |
| 896 | this.tabs.setTitleAt(0, I18n.translate("info_panel.tree.inheritance")); | 933 | this.tabs.setTitleAt(0, I18n.translate("info_panel.tree.structure")); |
| 897 | this.tabs.setTitleAt(1, I18n.translate("info_panel.tree.implementations")); | 934 | this.tabs.setTitleAt(1, I18n.translate("info_panel.tree.inheritance")); |
| 898 | this.tabs.setTitleAt(2, I18n.translate("info_panel.tree.calls")); | 935 | this.tabs.setTitleAt(2, I18n.translate("info_panel.tree.implementations")); |
| 936 | this.tabs.setTitleAt(3, I18n.translate("info_panel.tree.calls")); | ||
| 899 | this.logTabs.setTitleAt(0, I18n.translate("log_panel.users")); | 937 | this.logTabs.setTitleAt(0, I18n.translate("log_panel.users")); |
| 900 | this.logTabs.setTitleAt(1, I18n.translate("log_panel.messages")); | 938 | this.logTabs.setTitleAt(1, I18n.translate("log_panel.messages")); |
| 901 | this.connectionStatusLabel.setText(I18n.translate(connectionState == ConnectionState.NOT_CONNECTED ? "status.disconnected" : "status.connected")); | 939 | this.connectionStatusLabel.setText(I18n.translate(connectionState == ConnectionState.NOT_CONNECTED ? "status.disconnected" : "status.connected")); |
| @@ -907,6 +945,7 @@ public class Gui implements LanguageChangeListener { | |||
| 907 | this.deobfPanel.retranslateUi(); | 945 | this.deobfPanel.retranslateUi(); |
| 908 | this.deobfPanelPopupMenu.retranslateUi(); | 946 | this.deobfPanelPopupMenu.retranslateUi(); |
| 909 | this.infoPanel.retranslateUi(); | 947 | this.infoPanel.retranslateUi(); |
| 948 | this.structurePanel.retranslateUi(); | ||
| 910 | this.editors.values().forEach(EditorPanel::retranslateUi); | 949 | this.editors.values().forEach(EditorPanel::retranslateUi); |
| 911 | } | 950 | } |
| 912 | 951 | ||
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java index 4f7819e4..5217b25c 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java | |||
| @@ -57,10 +57,7 @@ import cuchaz.enigma.translation.mapping.serde.MappingParseException; | |||
| 57 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | 57 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; |
| 58 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 58 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 59 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | 59 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; |
| 60 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 60 | import cuchaz.enigma.translation.representation.entry.*; |
| 61 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 62 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 63 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 64 | import cuchaz.enigma.utils.I18n; | 61 | import cuchaz.enigma.utils.I18n; |
| 65 | import cuchaz.enigma.utils.Utils; | 62 | import cuchaz.enigma.utils.Utils; |
| 66 | import cuchaz.enigma.utils.validation.ValidationContext; | 63 | import cuchaz.enigma.utils.validation.ValidationContext; |
| @@ -395,6 +392,12 @@ public class GuiController implements ClientPacketHandler { | |||
| 395 | chp.invalidateMapped(); | 392 | chp.invalidateMapped(); |
| 396 | } | 393 | } |
| 397 | 394 | ||
| 395 | public StructureTreeNode getClassStructure(ClassEntry entry, boolean hideDeobfuscated) { | ||
| 396 | StructureTreeNode rootNode = new StructureTreeNode(this.project, entry, entry); | ||
| 397 | rootNode.load(this.project, hideDeobfuscated); | ||
| 398 | return rootNode; | ||
| 399 | } | ||
| 400 | |||
| 398 | public ClassInheritanceTreeNode getClassInheritance(ClassEntry entry) { | 401 | public ClassInheritanceTreeNode getClassInheritance(ClassEntry entry) { |
| 399 | Translator translator = project.getMapper().getDeobfuscator(); | 402 | Translator translator = project.getMapper().getDeobfuscator(); |
| 400 | ClassInheritanceTreeNode rootNode = indexTreeBuilder.buildClassInheritance(translator, entry); | 403 | ClassInheritanceTreeNode rootNode = indexTreeBuilder.buildClassInheritance(translator, entry); |
| @@ -454,6 +457,7 @@ public class GuiController implements ClientPacketHandler { | |||
| 454 | Entry<?> entry = reference.getNameableEntry(); | 457 | Entry<?> entry = reference.getNameableEntry(); |
| 455 | EntryMapping previous = project.getMapper().getDeobfMapping(entry); | 458 | EntryMapping previous = project.getMapper().getDeobfMapping(entry); |
| 456 | project.getMapper().mapFromObf(vc, entry, previous != null ? previous.withName(newName) : new EntryMapping(newName), true, validateOnly); | 459 | project.getMapper().mapFromObf(vc, entry, previous != null ? previous.withName(newName) : new EntryMapping(newName), true, validateOnly); |
| 460 | gui.showStructure(gui.getActiveEditor()); | ||
| 457 | 461 | ||
| 458 | if (validateOnly || !vc.canProceed()) return; | 462 | if (validateOnly || !vc.canProceed()) return; |
| 459 | 463 | ||
| @@ -466,6 +470,7 @@ public class GuiController implements ClientPacketHandler { | |||
| 466 | @Override | 470 | @Override |
| 467 | public void removeMapping(ValidationContext vc, EntryReference<Entry<?>, Entry<?>> reference) { | 471 | public void removeMapping(ValidationContext vc, EntryReference<Entry<?>, Entry<?>> reference) { |
| 468 | project.getMapper().removeByObf(vc, reference.getNameableEntry()); | 472 | project.getMapper().removeByObf(vc, reference.getNameableEntry()); |
| 473 | gui.showStructure(gui.getActiveEditor()); | ||
| 469 | 474 | ||
| 470 | if (!vc.canProceed()) return; | 475 | if (!vc.canProceed()) return; |
| 471 | 476 | ||
| @@ -504,6 +509,7 @@ public class GuiController implements ClientPacketHandler { | |||
| 504 | EntryRemapper mapper = project.getMapper(); | 509 | EntryRemapper mapper = project.getMapper(); |
| 505 | Entry<?> entry = reference.getNameableEntry(); | 510 | Entry<?> entry = reference.getNameableEntry(); |
| 506 | mapper.mapFromObf(vc, entry, new EntryMapping(mapper.deobfuscate(entry).getName())); | 511 | mapper.mapFromObf(vc, entry, new EntryMapping(mapper.deobfuscate(entry).getName())); |
| 512 | gui.showStructure(gui.getActiveEditor()); | ||
| 507 | 513 | ||
| 508 | if (!vc.canProceed()) return; | 514 | if (!vc.canProceed()) return; |
| 509 | 515 | ||
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java new file mode 100644 index 00000000..139923c5 --- /dev/null +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | package cuchaz.enigma.gui.panels; | ||
| 2 | |||
| 3 | import cuchaz.enigma.analysis.StructureTreeNode; | ||
| 4 | import cuchaz.enigma.gui.Gui; | ||
| 5 | import cuchaz.enigma.gui.util.GuiUtil; | ||
| 6 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 7 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 8 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.ParentedEntry; | ||
| 10 | import cuchaz.enigma.utils.I18n; | ||
| 11 | |||
| 12 | import javax.swing.*; | ||
| 13 | import javax.swing.tree.DefaultTreeCellRenderer; | ||
| 14 | import javax.swing.tree.TreePath; | ||
| 15 | import java.awt.*; | ||
| 16 | import java.awt.event.MouseAdapter; | ||
| 17 | import java.awt.event.MouseEvent; | ||
| 18 | |||
| 19 | public class StructurePanel extends JPanel { | ||
| 20 | private JPanel sortingPanel; | ||
| 21 | private JCheckBox hideDeobfuscated; | ||
| 22 | |||
| 23 | private JTree structureTree; | ||
| 24 | |||
| 25 | public StructurePanel(Gui gui) { | ||
| 26 | this.sortingPanel = new JPanel(); | ||
| 27 | this.hideDeobfuscated = new JCheckBox(I18n.translate("info_panel.tree.structure.hide_deobfuscated")); | ||
| 28 | this.hideDeobfuscated.addActionListener(event -> gui.showStructure(gui.getActiveEditor())); | ||
| 29 | this.sortingPanel.add(this.hideDeobfuscated); | ||
| 30 | this.sortingPanel.setVisible(false); | ||
| 31 | |||
| 32 | this.structureTree = new JTree(); | ||
| 33 | this.structureTree.setModel(null); | ||
| 34 | this.structureTree.setCellRenderer(new StructureTreeCellRenderer()); | ||
| 35 | this.structureTree.setShowsRootHandles(true); | ||
| 36 | this.structureTree.addMouseListener(new MouseAdapter() { | ||
| 37 | @Override | ||
| 38 | public void mouseClicked(MouseEvent event) { | ||
| 39 | if (event.getClickCount() >= 2 && event.getButton() == MouseEvent.BUTTON1) { | ||
| 40 | // get the selected node | ||
| 41 | TreePath path = structureTree.getSelectionPath(); | ||
| 42 | if (path == null) { | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | Object node = path.getLastPathComponent(); | ||
| 47 | if (node instanceof StructureTreeNode) { | ||
| 48 | gui.getController().navigateTo(((StructureTreeNode) node).getEntry()); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | }); | ||
| 53 | |||
| 54 | this.setLayout(new BorderLayout()); | ||
| 55 | this.add(this.sortingPanel, BorderLayout.NORTH); | ||
| 56 | this.add(new JScrollPane(this.structureTree)); | ||
| 57 | } | ||
| 58 | |||
| 59 | public JPanel getSortingPanel() { | ||
| 60 | return this.sortingPanel; | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Returns whether the "Hide Deobfuscated" option of this structure panel is selected. | ||
| 65 | */ | ||
| 66 | public boolean shouldHideDeobfuscated() { | ||
| 67 | return this.hideDeobfuscated.isSelected(); | ||
| 68 | } | ||
| 69 | |||
| 70 | public JTree getStructureTree() { | ||
| 71 | return this.structureTree; | ||
| 72 | } | ||
| 73 | |||
| 74 | public void retranslateUi() { | ||
| 75 | this.hideDeobfuscated.setText(I18n.translate("info_panel.tree.structure.hide_deobfuscated")); | ||
| 76 | } | ||
| 77 | |||
| 78 | class StructureTreeCellRenderer extends DefaultTreeCellRenderer { | ||
| 79 | |||
| 80 | @Override | ||
| 81 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { | ||
| 82 | JComponent c = (JComponent) super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); | ||
| 83 | ParentedEntry entry = ((StructureTreeNode) value).getEntry(); | ||
| 84 | |||
| 85 | if (entry instanceof ClassEntry) { | ||
| 86 | this.setIcon(GuiUtil.CLASS_ICON); | ||
| 87 | } else if (entry instanceof MethodEntry) { | ||
| 88 | this.setIcon(((MethodEntry) entry).isConstructor() ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); | ||
| 89 | } else if (entry instanceof FieldEntry) { | ||
| 90 | this.setIcon(GuiUtil.FIELD_ICON); | ||
| 91 | } | ||
| 92 | |||
| 93 | this.setText(value.toString()); | ||
| 94 | |||
| 95 | return c; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java index b898eac3..20d6a0eb 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java | |||
| @@ -3,8 +3,6 @@ package cuchaz.enigma.gui.stats; | |||
| 3 | import cuchaz.enigma.EnigmaProject; | 3 | import cuchaz.enigma.EnigmaProject; |
| 4 | import cuchaz.enigma.ProgressListener; | 4 | import cuchaz.enigma.ProgressListener; |
| 5 | import cuchaz.enigma.analysis.index.EntryIndex; | 5 | import cuchaz.enigma.analysis.index.EntryIndex; |
| 6 | import cuchaz.enigma.api.service.NameProposalService; | ||
| 7 | import cuchaz.enigma.api.service.ObfuscationTestService; | ||
| 8 | import cuchaz.enigma.translation.mapping.EntryRemapper; | 6 | import cuchaz.enigma.translation.mapping.EntryRemapper; |
| 9 | import cuchaz.enigma.translation.mapping.EntryResolver; | 7 | import cuchaz.enigma.translation.mapping.EntryResolver; |
| 10 | import cuchaz.enigma.translation.mapping.ResolutionStrategy; | 8 | import cuchaz.enigma.translation.mapping.ResolutionStrategy; |
| @@ -15,18 +13,16 @@ import cuchaz.enigma.utils.I18n; | |||
| 15 | import java.util.*; | 13 | import java.util.*; |
| 16 | 14 | ||
| 17 | public class StatsGenerator { | 15 | public class StatsGenerator { |
| 16 | private final EnigmaProject project; | ||
| 18 | private final EntryIndex entryIndex; | 17 | private final EntryIndex entryIndex; |
| 19 | private final EntryRemapper mapper; | 18 | private final EntryRemapper mapper; |
| 20 | private final EntryResolver entryResolver; | 19 | private final EntryResolver entryResolver; |
| 21 | private final List<ObfuscationTestService> obfuscationTestServices; | ||
| 22 | private final List<NameProposalService> nameProposalServices; | ||
| 23 | 20 | ||
| 24 | public StatsGenerator(EnigmaProject project) { | 21 | public StatsGenerator(EnigmaProject project) { |
| 25 | entryIndex = project.getJarIndex().getEntryIndex(); | 22 | this.project = project; |
| 26 | mapper = project.getMapper(); | 23 | this.entryIndex = project.getJarIndex().getEntryIndex(); |
| 27 | entryResolver = project.getJarIndex().getEntryResolver(); | 24 | this.mapper = project.getMapper(); |
| 28 | obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE); | 25 | this.entryResolver = project.getJarIndex().getEntryResolver(); |
| 29 | nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE); | ||
| 30 | } | 26 | } |
| 31 | 27 | ||
| 32 | public StatsResult generate(ProgressListener progress, Set<StatsMember> includedMembers, String topLevelPackage, boolean includeSynthetic) { | 28 | public StatsResult generate(ProgressListener progress, Set<StatsMember> includedMembers, String topLevelPackage, boolean includeSynthetic) { |
| @@ -111,36 +107,9 @@ public class StatsGenerator { | |||
| 111 | } | 107 | } |
| 112 | 108 | ||
| 113 | private void update(Map<String, Integer> counts, Entry<?> entry) { | 109 | private void update(Map<String, Integer> counts, Entry<?> entry) { |
| 114 | if (isObfuscated(entry)) { | 110 | if (project.isObfuscated(entry)) { |
| 115 | String parent = mapper.deobfuscate(entry.getAncestry().get(0)).getName().replace('/', '.'); | 111 | String parent = mapper.deobfuscate(entry.getAncestry().get(0)).getName().replace('/', '.'); |
| 116 | counts.put(parent, counts.getOrDefault(parent, 0) + 1); | 112 | counts.put(parent, counts.getOrDefault(parent, 0) + 1); |
| 117 | } | 113 | } |
| 118 | } | 114 | } |
| 119 | |||
| 120 | private boolean isObfuscated(Entry<?> entry) { | ||
| 121 | String name = entry.getName(); | ||
| 122 | |||
| 123 | if (!obfuscationTestServices.isEmpty()) { | ||
| 124 | for (ObfuscationTestService service : obfuscationTestServices) { | ||
| 125 | if (service.testDeobfuscated(entry)) { | ||
| 126 | return false; | ||
| 127 | } | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | if (!nameProposalServices.isEmpty()) { | ||
| 132 | for (NameProposalService service : nameProposalServices) { | ||
| 133 | if (service.proposeName(entry, mapper).isPresent()) { | ||
| 134 | return false; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | String mappedName = mapper.deobfuscate(entry).getName(); | ||
| 140 | if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) { | ||
| 141 | return false; | ||
| 142 | } | ||
| 143 | |||
| 144 | return true; | ||
| 145 | } | ||
| 146 | } | 115 | } |
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java index 7fe942d0..6393913d 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/util/GuiUtil.java | |||
| @@ -1,24 +1,25 @@ | |||
| 1 | package cuchaz.enigma.gui.util; | 1 | package cuchaz.enigma.gui.util; |
| 2 | 2 | ||
| 3 | import java.awt.Color; | 3 | import cuchaz.enigma.utils.Os; |
| 4 | import java.awt.Cursor; | 4 | |
| 5 | import java.awt.Desktop; | 5 | import javax.imageio.ImageIO; |
| 6 | import java.awt.Font; | 6 | import javax.swing.*; |
| 7 | import java.awt.*; | ||
| 7 | import java.awt.event.MouseAdapter; | 8 | import java.awt.event.MouseAdapter; |
| 8 | import java.awt.event.MouseEvent; | 9 | import java.awt.event.MouseEvent; |
| 9 | import java.awt.font.TextAttribute; | 10 | import java.awt.font.TextAttribute; |
| 10 | import java.io.IOException; | 11 | import java.io.IOException; |
| 12 | import java.io.InputStream; | ||
| 11 | import java.net.URI; | 13 | import java.net.URI; |
| 12 | import java.net.URISyntaxException; | 14 | import java.net.URISyntaxException; |
| 13 | import java.util.Map; | 15 | import java.util.Map; |
| 14 | 16 | ||
| 15 | import javax.swing.JComponent; | ||
| 16 | import javax.swing.JLabel; | ||
| 17 | import javax.swing.ToolTipManager; | ||
| 18 | |||
| 19 | import cuchaz.enigma.utils.Os; | ||
| 20 | |||
| 21 | public class GuiUtil { | 17 | public class GuiUtil { |
| 18 | public static final Icon CLASS_ICON = loadIcon("class"); | ||
| 19 | public static final Icon METHOD_ICON = loadIcon("method"); | ||
| 20 | public static final Icon FIELD_ICON = loadIcon("field"); | ||
| 21 | public static final Icon CONSTRUCTOR_ICON = loadIcon("constructor"); | ||
| 22 | |||
| 22 | public static void openUrl(String url) { | 23 | public static void openUrl(String url) { |
| 23 | try { | 24 | try { |
| 24 | switch (Os.getOs()) { | 25 | switch (Os.getOs()) { |
| @@ -70,4 +71,15 @@ public class GuiUtil { | |||
| 70 | return link; | 71 | return link; |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 74 | public static Icon loadIcon(String name) { | ||
| 75 | try { | ||
| 76 | InputStream inputStream = GuiUtil.class.getResourceAsStream("/icons/" + name + ".png"); | ||
| 77 | Image image = ImageIO.read(inputStream).getScaledInstance(ScaleUtil.scale(16), ScaleUtil.scale(16), Image.SCALE_DEFAULT); | ||
| 78 | return new ImageIcon(image); | ||
| 79 | } catch (IOException e) { | ||
| 80 | e.printStackTrace(); | ||
| 81 | } | ||
| 82 | |||
| 83 | return null; | ||
| 84 | } | ||
| 73 | } | 85 | } |