package nf.co.haxter.gui.tabs;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import nf.co.haxter.gui.MainWindow;
import nf.co.haxter.gui.layouts.WrapLayout;
import nf.co.haxter.util.BytecodeUtils;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import static nf.co.haxter.util.MiscUtils.parse;
import static nf.co.haxter.util.MiscUtils.parseBack;
public class ClassInfoPanel extends JPanel {
private DefaultListModel<String> interfaceModel;
private final ButtonGroup buttonGroup = new ButtonGroup();
private JRadioButton rdbtnPublic;
private JRadioButton rdbtnProtected;
private JRadioButton rdbtnPrivate;
private JRadioButton rdbtnDefault;
private JCheckBox chckbxStatic;
private JCheckBox chckbxAbstract;
private JCheckBox chckbxFinal;
private JCheckBox chckbxEnum;
private JPanel panelNamesInner;
private JLabel lblClassName;
private JTextField textFieldClassName;
private JLabel lblSuperClassName;
private JTextField textFieldSuperClassName;
private JLabel lblPlaceholder;
private JTextField textFieldSignature;
private JLabel lblOuterMethod;
private JTextField textFieldOuterMethod;
private JLabel lblOuterMethodDescriptor;
private JTextField textFieldOuterMethodDesc;
private JLabel lblSourceFile;
private JTextField textFieldSourceFile;
private JLabel lblOuterClass;
private JTextField textFieldOuterClass;
private JLabel lblSourceDebug;
private JTextField textFieldSourceDebug;
private JPanel panelMisc;
private JComboBox<ClassVersion> comboBoxClassVersion;
private JLabel lblClassVersion;
private JList<String> listInterfaces;
private JPanel panelInterfaceControls;
private JButton btnAddInterface;
private JButton btnRemoveInterface;
private JButton btnRename;
/**
* Create the panel.
*/
public ClassInfoPanel(ClassNode cNode) {
int v = cNode.version;
for (int i = 0; i < ClassVersion.values().length; i++) {
if (ClassVersion.values()[i].versionOpcode == v) {
v = i;
break;
}
}
JPanel panelNames = new JPanel();
JPanel panelModifiers = new JPanel();
panelModifiers.setLayout(new BorderLayout(0, 0));
JPanel panelAccessModifiers = new JPanel();
panelModifiers.add(panelAccessModifiers, BorderLayout.WEST);
panelAccessModifiers.setLayout(new BoxLayout(panelAccessModifiers, BoxLayout.Y_AXIS));
rdbtnPublic = new JRadioButton("PUBLIC");
buttonGroup.add(rdbtnPublic);
panelAccessModifiers.add(rdbtnPublic);
rdbtnProtected = new JRadioButton("PROTECTED");
buttonGroup.add(rdbtnProtected);
panelAccessModifiers.add(rdbtnProtected);
rdbtnPrivate = new JRadioButton("PRIVATE");
buttonGroup.add(rdbtnPrivate);
panelAccessModifiers.add(rdbtnPrivate);
rdbtnDefault = new JRadioButton("DEFAULT");
buttonGroup.add(rdbtnDefault);
panelAccessModifiers.add(rdbtnDefault);
JPanel panelOtherModifiers = new JPanel();
panelModifiers.add(panelOtherModifiers, BorderLayout.EAST);
panelOtherModifiers.setLayout(new WrapLayout());
chckbxStatic = new JCheckBox("STATIC");
panelOtherModifiers.add(chckbxStatic);
chckbxAbstract = new JCheckBox("ABSTRACT");
panelOtherModifiers.add(chckbxAbstract);
chckbxFinal = new JCheckBox("FINAL");
panelOtherModifiers.add(chckbxFinal);
chckbxEnum = new JCheckBox("ENUM");
panelOtherModifiers.add(chckbxEnum);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
panelMisc = new JPanel();
tabbedPane.addTab("Misc.", null, panelMisc, null);
panelMisc.setLayout(new GridLayout(0, 2, 0, 0));
lblClassVersion = new JLabel("Class Version: ");
panelMisc.add(lblClassVersion);
comboBoxClassVersion = new JComboBox<ClassVersion>();
comboBoxClassVersion.setModel(new DefaultComboBoxModel(ClassVersion.values()));
comboBoxClassVersion.setSelectedIndex(v);
panelMisc.add(comboBoxClassVersion);
tabbedPane.addTab("Modifiers", panelModifiers);
tabbedPane.addTab("Names", panelNames);
panelNames.setLayout(new BorderLayout(0, 0));
panelNamesInner = new JPanel();
panelNames.add(panelNamesInner);
panelNamesInner.setLayout(new GridLayout(0, 2, 0, 0));
lblClassName = new JLabel("Class Name: ");
panelNamesInner.add(lblClassName);
textFieldClassName = new JTextField(parse(cNode.name));
panelNamesInner.add(textFieldClassName);
textFieldClassName.setColumns(10);
lblSuperClassName = new JLabel("Super Class Name: ");
panelNamesInner.add(lblSuperClassName);
textFieldSuperClassName = new JTextField(parse(cNode.superName));
panelNamesInner.add(textFieldSuperClassName);
textFieldSuperClassName.setColumns(10);
lblPlaceholder = new JLabel("Signature: ");
panelNamesInner.add(lblPlaceholder);
textFieldSignature = new JTextField(parse(cNode.signature));
panelNamesInner.add(textFieldSignature);
textFieldSignature.setColumns(10);
lblOuterClass = new JLabel("Outer Class: ");
panelNamesInner.add(lblOuterClass);
textFieldOuterClass = new JTextField(parse(cNode.outerClass));
panelNamesInner.add(textFieldOuterClass);
textFieldOuterClass.setColumns(10);
lblOuterMethod = new JLabel("Outer Method: ");
panelNamesInner.add(lblOuterMethod);
textFieldOuterMethod = new JTextField(parse(cNode.outerMethod));
panelNamesInner.add(textFieldOuterMethod);
textFieldOuterMethod.setColumns(10);
lblOuterMethodDescriptor = new JLabel("Outer Method Descriptor: ");
panelNamesInner.add(lblOuterMethodDescriptor);
textFieldOuterMethodDesc = new JTextField(parse(cNode.outerMethodDesc));
panelNamesInner.add(textFieldOuterMethodDesc);
textFieldOuterMethodDesc.setColumns(10);
lblSourceFile = new JLabel("Source File: ");
panelNamesInner.add(lblSourceFile);
textFieldSourceFile = new JTextField(parse(cNode.sourceFile));
panelNamesInner.add(textFieldSourceFile);
textFieldSourceFile.setColumns(10);
lblSourceDebug = new JLabel("Source Debug: ");
panelNamesInner.add(lblSourceDebug);
textFieldSourceDebug = new JTextField(parse(cNode.sourceDebug));
panelNamesInner.add(textFieldSourceDebug);
textFieldSourceDebug.setColumns(10);
add(tabbedPane);
JPanel panelInterfaces = new JPanel();
tabbedPane.addTab("Interfaces", null, panelInterfaces, null);
panelInterfaces.setLayout(new BorderLayout(0, 0));
listInterfaces = new JList<String>();
listInterfaces.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
panelInterfaces.add(listInterfaces);
interfaceModel = new DefaultListModel<String>();
for (String inter : (List<String>) cNode.interfaces) {
interfaceModel.addElement(inter);
}
listInterfaces.setModel(interfaceModel);
panelInterfaceControls = new JPanel();
panelInterfaces.add(panelInterfaceControls, BorderLayout.NORTH);
panelInterfaceControls.setLayout(new WrapLayout());
btnAddInterface = new JButton("Add...");
panelInterfaceControls.add(btnAddInterface);
btnAddInterface.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent paramActionEvent) {
String inter = JOptionPane.showInputDialog("Interface:");
if (inter == null) {
return;
}
interfaceModel.addElement(inter);
}
});
btnRemoveInterface = new JButton("Remove");
btnRemoveInterface.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent paramActionEvent) {
if (listInterfaces.getSelectedValue() != null) {
interfaceModel.removeElement(listInterfaces.getSelectedValue());
}
}
});
btnRename = new JButton("Rename...");
btnRename.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent paramActionEvent) {
if (listInterfaces.getSelectedValue() != null) {
String s = JOptionPane.showInputDialog("Interface:", listInterfaces.getSelectedValue());
if (s != null) {
interfaceModel.set(listInterfaces.getSelectedIndex(), s);
}
}
}
});
panelInterfaceControls.add(btnRename);
panelInterfaceControls.add(btnRemoveInterface);
initInitialModifiers(cNode);
}
public void initInitialModifiers(ClassNode cn) {
boolean isPublic = BytecodeUtils.isPublic(cn.access);
boolean isPrivate = BytecodeUtils.isPrivate(cn.access);
boolean isProtected = BytecodeUtils.isProtected(cn.access);
this.rdbtnPublic.setSelected(isPublic);
this.rdbtnPrivate.setSelected(isPrivate);
this.rdbtnProtected.setSelected(isProtected);
this.rdbtnDefault.setSelected(!isPublic && !isPrivate && !isProtected);
this.chckbxAbstract.setSelected(BytecodeUtils.isAbstract(cn.access));
this.chckbxEnum.setSelected(BytecodeUtils.isEnum(cn.access));
this.chckbxFinal.setSelected(BytecodeUtils.isFinal(cn.access));
this.chckbxStatic.setSelected(BytecodeUtils.isStatic(cn.access));
}
public void saveClassProperties(ClassNode cn) {
cn.version = ((ClassVersion) this.comboBoxClassVersion.getSelectedItem()).versionOpcode;
cn.access = 0;
if (this.rdbtnPublic.isSelected()) {
cn.access |= Opcodes.ACC_PUBLIC;
} else if (this.rdbtnProtected.isSelected()) {
cn.access |= Opcodes.ACC_PROTECTED;
} else if (this.rdbtnPrivate.isSelected()) {
cn.access |= Opcodes.ACC_PRIVATE;
}
if (this.chckbxAbstract.isSelected()) {
cn.access |= Opcodes.ACC_ABSTRACT;
}
if (this.chckbxFinal.isSelected()) {
cn.access |= Opcodes.ACC_FINAL;
}
if (this.chckbxStatic.isSelected()) {
cn.access |= Opcodes.ACC_STATIC;
}
if (this.chckbxEnum.isSelected()) {
cn.access |= Opcodes.ACC_ENUM;
}
cn.name = this.textFieldClassName.getText();
cn.superName = this.textFieldSuperClassName.getText();
cn.outerMethod = parseBack(this.textFieldOuterMethod.getText());
cn.outerMethodDesc = parseBack(this.textFieldOuterMethodDesc.getText());
cn.outerClass = parseBack(this.textFieldOuterClass.getText());
cn.signature = parseBack(this.textFieldSignature.getText());
cn.sourceFile = parseBack(this.textFieldSourceFile.getText());
cn.sourceDebug = parseBack(this.textFieldSourceDebug.getText());
cn.interfaces = new ArrayList<String>();
Enumeration<String> inters = this.interfaceModel.elements();
while (inters.hasMoreElements()) {
cn.interfaces.add(inters.nextElement());
}
}
/**
* An enumerator of Java class versions.
*
* @author blootooby
*/
private static enum ClassVersion implements Opcodes {
/*
* FIXME I'm considering changing this. It feels sloppy to me. :( - blootooby
*/
JRE1(V1_1), JRE2(V1_2), JRE3(V1_3), JRE4(V1_4), JRE5(V1_5), JRE6(V1_6), JRE7(V1_7), JRE8(V1_8);
public int versionOpcode;
private ClassVersion(int opcode) {
this.versionOpcode = opcode;
}
@Override
public String toString() {
switch (this.versionOpcode) {
case V1_1:
return "1.1";
case V1_2:
return "1.2";
case V1_3:
return "1.3";
case V1_4:
return "1.4";
case V1_5:
return "1.5";
case V1_6:
return "1.6";
case V1_7:
return "1.7";
case V1_8:
return "1.8";
default:
return "Unknown";
}
}
}
}