From 68aaf143193201ecf71ced2ae6cd9eca7a0225a1 Mon Sep 17 00:00:00 2001 From: Juuxel Date: Tue, 15 Dec 2020 23:28:05 +0200 Subject: Add interface/enum/annotation icons and modifier displays - Adds icons in the sidebar and structure panel for interfaces, enums and annotations. - Adds some modifiers (final, default, abstract, static) to the structure panel. --- .../main/java/cuchaz/enigma/gui/ClassSelector.java | 19 ++++++++++-- .../cuchaz/enigma/gui/panels/StructurePanel.java | 11 +++++-- .../main/java/cuchaz/enigma/gui/util/GuiUtil.java | 24 +++++++++++++++ .../src/main/resources/icons/annotation.png | Bin 0 -> 877 bytes enigma-swing/src/main/resources/icons/enum.png | Bin 0 -> 506 bytes .../src/main/resources/icons/interface.png | Bin 0 -> 538 bytes .../cuchaz/enigma/analysis/StructureTreeNode.java | 33 +++++++++++++++++++++ .../translation/representation/AccessFlags.java | 8 +++++ 8 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 enigma-swing/src/main/resources/icons/annotation.png create mode 100644 enigma-swing/src/main/resources/icons/enum.png create mode 100644 enigma-swing/src/main/resources/icons/interface.png 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 b27832b..91c9705 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/ClassSelector.java @@ -11,6 +11,7 @@ package cuchaz.enigma.gui; +import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.*; @@ -70,8 +71,22 @@ public class ClassSelector extends JTree { } }); - final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); - renderer.setLeafIcon(GuiUtil.CLASS_ICON); + final DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { + { + setLeafIcon(GuiUtil.CLASS_ICON); + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + + if (leaf && value instanceof ClassSelectorClassNode) { + setIcon(GuiUtil.getClassIcon(gui, ((ClassSelectorClassNode) value).getObfEntry())); + } + + return this; + } + }; setCellRenderer(renderer); final JTree tree = this; 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 index 139923c..12f1d75 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/StructurePanel.java @@ -31,7 +31,7 @@ public class StructurePanel extends JPanel { this.structureTree = new JTree(); this.structureTree.setModel(null); - this.structureTree.setCellRenderer(new StructureTreeCellRenderer()); + this.structureTree.setCellRenderer(new StructureTreeCellRenderer(gui)); this.structureTree.setShowsRootHandles(true); this.structureTree.addMouseListener(new MouseAdapter() { @Override @@ -76,6 +76,11 @@ public class StructurePanel extends JPanel { } class StructureTreeCellRenderer extends DefaultTreeCellRenderer { + private final Gui gui; + + StructureTreeCellRenderer(Gui gui) { + this.gui = gui; + } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { @@ -83,14 +88,14 @@ public class StructurePanel extends JPanel { ParentedEntry entry = ((StructureTreeNode) value).getEntry(); if (entry instanceof ClassEntry) { - this.setIcon(GuiUtil.CLASS_ICON); + this.setIcon(GuiUtil.getClassIcon(gui, (ClassEntry) entry)); } else if (entry instanceof MethodEntry) { this.setIcon(((MethodEntry) entry).isConstructor() ? GuiUtil.CONSTRUCTOR_ICON : GuiUtil.METHOD_ICON); } else if (entry instanceof FieldEntry) { this.setIcon(GuiUtil.FIELD_ICON); } - this.setText(value.toString()); + this.setText("" + ((StructureTreeNode) value).toHtml()); return c; } 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 6393913..95f0853 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,5 +1,8 @@ package cuchaz.enigma.gui.util; +import cuchaz.enigma.gui.Gui; +import cuchaz.enigma.translation.representation.AccessFlags; +import cuchaz.enigma.translation.representation.entry.ClassEntry; import cuchaz.enigma.utils.Os; import javax.imageio.ImageIO; @@ -16,6 +19,9 @@ import java.util.Map; public class GuiUtil { public static final Icon CLASS_ICON = loadIcon("class"); + public static final Icon INTERFACE_ICON = loadIcon("interface"); + public static final Icon ENUM_ICON = loadIcon("enum"); + public static final Icon ANNOTATION_ICON = loadIcon("annotation"); public static final Icon METHOD_ICON = loadIcon("method"); public static final Icon FIELD_ICON = loadIcon("field"); public static final Icon CONSTRUCTOR_ICON = loadIcon("constructor"); @@ -82,4 +88,22 @@ public class GuiUtil { return null; } + + public static Icon getClassIcon(Gui gui, ClassEntry entry) { + AccessFlags access = gui.getController().project.getJarIndex().getEntryIndex().getClassAccess(entry); + + if (access != null) { + if (access.isAnnotation()) { + return ANNOTATION_ICON; + } else if (access.isInterface()) { + return INTERFACE_ICON; + } else if (access.isEnum()) { + return ENUM_ICON; + } + + // TODO: Record icon? + } + + return CLASS_ICON; + } } diff --git a/enigma-swing/src/main/resources/icons/annotation.png b/enigma-swing/src/main/resources/icons/annotation.png new file mode 100644 index 0000000..9589a67 Binary files /dev/null and b/enigma-swing/src/main/resources/icons/annotation.png differ diff --git a/enigma-swing/src/main/resources/icons/enum.png b/enigma-swing/src/main/resources/icons/enum.png new file mode 100644 index 0000000..b64dc82 Binary files /dev/null and b/enigma-swing/src/main/resources/icons/enum.png differ diff --git a/enigma-swing/src/main/resources/icons/interface.png b/enigma-swing/src/main/resources/icons/interface.png new file mode 100644 index 0000000..fc2bfe5 Binary files /dev/null and b/enigma-swing/src/main/resources/icons/interface.png differ diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java index f310aa7..ac3a381 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java @@ -4,10 +4,12 @@ import cuchaz.enigma.EnigmaProject; import cuchaz.enigma.api.service.NameProposalService; import cuchaz.enigma.translation.TranslateResult; import cuchaz.enigma.translation.mapping.EntryRemapper; +import cuchaz.enigma.translation.representation.AccessFlags; import cuchaz.enigma.translation.representation.TypeDescriptor; import cuchaz.enigma.translation.representation.entry.*; import javax.swing.tree.DefaultMutableTreeNode; +import java.util.ArrayList; import java.util.List; public class StructureTreeNode extends DefaultMutableTreeNode { @@ -90,6 +92,37 @@ public class StructureTreeNode extends DefaultMutableTreeNode { return result; } + public String toHtml() { + List modifiers = new ArrayList<>(); + + if (this.entry instanceof DefEntry) { + AccessFlags access = ((DefEntry) this.entry).getAccess(); + boolean isInterfaceMethod = false; + + if (this.entry instanceof MethodEntry && this.entry.getParent() instanceof ClassDefEntry) { + isInterfaceMethod = ((ClassDefEntry) this.entry.getParent()).getAccess().isInterface(); + } + + if (access.isStatic() && !access.isEnum()) { + // Static member, but not an enum constant + modifiers.add("static"); + } else if (isInterfaceMethod && !access.isAbstract()) { + // Non-static default interface method + modifiers.add("default"); + } + + if (access.isAbstract() && !access.isInterface() && !isInterfaceMethod) { + // Abstract, but not an interface or an interface method (they're always abstract) + modifiers.add("abstract"); + } else if (access.isFinal() && !access.isEnum()) { + // Final, but not an enum or an enum constant (they're always final) + modifiers.add("final"); + } + } + + return "" + String.join(" ", modifiers) + " " + toString(); + } + private String parseArgs(List args) { if (args.size() > 0) { String result = "("; diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java index b280eef..e8480a2 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java @@ -51,6 +51,14 @@ public class AccessFlags { return (flags & Opcodes.ACC_INTERFACE) != 0; } + public boolean isAbstract() { + return (flags & Opcodes.ACC_ABSTRACT) != 0; + } + + public boolean isAnnotation() { + return (flags & Opcodes.ACC_ANNOTATION) != 0; + } + public AccessFlags setPrivate() { this.setVisibility(Opcodes.ACC_PRIVATE); return this; -- cgit v1.2.3 From 591453edd88cae642ed18b4e71e35b94db093259 Mon Sep 17 00:00:00 2001 From: Juuxel Date: Sat, 23 Jan 2021 17:23:34 +0200 Subject: Exclude abstract modifier from enum classes --- enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java index ac3a381..8782b8f 100644 --- a/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java +++ b/enigma/src/main/java/cuchaz/enigma/analysis/StructureTreeNode.java @@ -111,8 +111,8 @@ public class StructureTreeNode extends DefaultMutableTreeNode { modifiers.add("default"); } - if (access.isAbstract() && !access.isInterface() && !isInterfaceMethod) { - // Abstract, but not an interface or an interface method (they're always abstract) + if (access.isAbstract() && !access.isInterface() && !isInterfaceMethod && !access.isEnum()) { + // Abstract, but not an interface, an interface method or an enum class (abstract is the default or meaningless) modifiers.add("abstract"); } else if (access.isFinal() && !access.isEnum()) { // Final, but not an enum or an enum constant (they're always final) -- cgit v1.2.3