diff --git a/build.gradle b/build.gradle index 950668e..d5686b7 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { } group 'cn.enaium' -version '0.8.0' +version '0.9.0' sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/src/main/java/cn/enaium/joe/JavaOctetEditor.java b/src/main/java/cn/enaium/joe/JavaOctetEditor.java index 7d03d04..4b32b97 100644 --- a/src/main/java/cn/enaium/joe/JavaOctetEditor.java +++ b/src/main/java/cn/enaium/joe/JavaOctetEditor.java @@ -49,21 +49,25 @@ public class JavaOctetEditor { public Jar jar; - public FileTabbedPanel fileTabbedPanel = new FileTabbedPanel(); + public FileTabbedPanel fileTabbedPanel; - public FileTreePanel fileTreePanel = new FileTreePanel(); + public FileTreePanel fileTreePanel; - public BottomPanel bottomPanel = new BottomPanel(); + public BottomPanel bottomPanel; - public ConfigManager configManager = new ConfigManager(); + public ConfigManager configManager; public JavaOctetEditor() { instance = this; + configManager = new ConfigManager(); + configManager.load(); + Runtime.getRuntime().addShutdownHook(new Thread(configManager::save)); + fileTabbedPanel = new FileTabbedPanel(); + fileTreePanel = new FileTreePanel(); + bottomPanel = new BottomPanel(); } public void run() { - configManager.load(); - Runtime.getRuntime().addShutdownHook(new Thread(configManager::save)); ToolTipManager.sharedInstance().setInitialDelay(0); @@ -91,7 +95,7 @@ public void run() { window.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - MessageUtil.confirm(LangUtil.i18n("dialog.wantCloseWindow"), "WARNING", () -> { + MessageUtil.confirm(LangUtil.i18n("dialog.wantCloseWindow"), LangUtil.i18n("warning"), () -> { window.dispose(); System.exit(0); }, () -> { diff --git a/src/main/java/cn/enaium/joe/annotation/NoUI.java b/src/main/java/cn/enaium/joe/annotation/NoUI.java new file mode 100644 index 0000000..c899119 --- /dev/null +++ b/src/main/java/cn/enaium/joe/annotation/NoUI.java @@ -0,0 +1,31 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Enaium + * @since 0.9.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface NoUI { +} diff --git a/src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java b/src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java index af616ee..46ad0b4 100644 --- a/src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java +++ b/src/main/java/cn/enaium/joe/config/extend/ApplicationConfig.java @@ -16,10 +16,14 @@ package cn.enaium.joe.config.extend; +import cn.enaium.joe.annotation.NoUI; import cn.enaium.joe.config.Config; import cn.enaium.joe.config.value.ModeValue; +import cn.enaium.joe.config.value.StringSetValue; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; /** * @author Enaium @@ -28,6 +32,8 @@ public class ApplicationConfig extends Config { public final ModeValue decompilerMode = new ModeValue("Decompiler", "CFR", "Java Decompiler", Arrays.asList("CFR", "Procyon", "JD-Core")); public final ModeValue language = new ModeValue("Language", "System", "UI language", Arrays.asList("System", "zh_CN", "en_US")); + @NoUI + public final StringSetValue loadRecent = new StringSetValue("Load Recent", new HashSet<>(), ""); public ApplicationConfig() { super("Application"); diff --git a/src/main/java/cn/enaium/joe/config/value/StringSetValue.java b/src/main/java/cn/enaium/joe/config/value/StringSetValue.java new file mode 100644 index 0000000..0b61c66 --- /dev/null +++ b/src/main/java/cn/enaium/joe/config/value/StringSetValue.java @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.config.value; + +import java.util.List; +import java.util.Set; + +/** + * @author Enaium + * @since 0.9.0 + */ +public class StringSetValue extends Value>{ + public StringSetValue(String name, Set value, String description) { + super(name, value, description); + } +} diff --git a/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java b/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java index 43cdef7..b54ddb9 100644 --- a/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java +++ b/src/main/java/cn/enaium/joe/dialog/ConfigDialog.java @@ -17,6 +17,7 @@ package cn.enaium.joe.dialog; import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.annotation.NoUI; import cn.enaium.joe.config.Config; import cn.enaium.joe.config.value.*; import cn.enaium.joe.util.LangUtil; @@ -44,6 +45,12 @@ public ConfigDialog(Config config) { try { for (Field declaredField : config.getClass().getDeclaredFields()) { declaredField.setAccessible(true); + + + if (declaredField.isAnnotationPresent(NoUI.class)) { + continue; + } + Object o = declaredField.get(config); if (o instanceof Value) { diff --git a/src/main/java/cn/enaium/joe/gui/component/InstructionComboBox.java b/src/main/java/cn/enaium/joe/gui/component/InstructionComboBox.java new file mode 100644 index 0000000..2df1d4c --- /dev/null +++ b/src/main/java/cn/enaium/joe/gui/component/InstructionComboBox.java @@ -0,0 +1,31 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.gui.component; + +import javax.swing.*; + +/** + * @author Enaium + * @since 0.9.0 + */ +public class InstructionComboBox extends JComboBox { + public InstructionComboBox() { + super(new String[]{"Opcode", "Int", "Var", "Type", "Field", "Method", "InvokeDynamic", "Jump", "Label", "LDC", "Incr", "TableSwitch", "LookupSwitch", "MultiANewArray", "Frame", "Line"}); + } +} + + diff --git a/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java b/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java index fe87ed7..47d853d 100644 --- a/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java +++ b/src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java @@ -31,7 +31,7 @@ public class LabelNodeComboBox extends JComboBox { public LabelNodeComboBox(AbstractInsnNode instruction, LabelNode select) { super(new DefaultComboBoxModel<>()); LabelNodeWrapper selected = null; - for (AbstractInsnNode abstractInsnNode : OpcodeUtil.getInstructionList(instruction)) { + for (AbstractInsnNode abstractInsnNode : OpcodeUtil.getInstructionList(select)) { if (abstractInsnNode instanceof LabelNode) { LabelNodeWrapper anObject = new LabelNodeWrapper(((LabelNode) abstractInsnNode)); if (abstractInsnNode.equals(select)) { diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java index 1dcc841..3234825 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/confirm/BootstrapMethodArgumentEditPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.confirm; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.wrapper.Wrapper; import org.objectweb.asm.Handle; @@ -40,7 +41,7 @@ public BootstrapMethodArgumentEditPanel(Wrapper wrapper) { } add(new JScrollPane(objectJList), BorderLayout.CENTER); add(new JPanel() {{ - add(new JButton("Add") {{ + add(new JButton(LangUtil.i18n("button.add")) {{ addActionListener(e -> { MessageUtil.confirm(new ConfirmPanel() {{ setLayout(new BorderLayout()); @@ -49,9 +50,9 @@ public BootstrapMethodArgumentEditPanel(Wrapper wrapper) { add(left, BorderLayout.WEST); add(right, BorderLayout.CENTER); JComboBox jComboBox = new JComboBox<>(new String[]{"String", "float", "double", "int", "long", "Class"}); - left.add(new JLabel("Type:")); + left.add(new JLabel(LangUtil.i18n("instruction.type"))); right.add(jComboBox); - left.add(new JLabel("Var:")); + left.add(new JLabel(LangUtil.i18n("instruction.var"))); JTextField ldc = new JTextField(); right.add(ldc); setConfirm(() -> { @@ -79,7 +80,7 @@ public BootstrapMethodArgumentEditPanel(Wrapper wrapper) { objectDefaultListModel.addElement(value); } }); - }}, "Add"); + }}, LangUtil.i18n("button.add")); }); }}); add(new JButton("Add Handle") {{ @@ -93,7 +94,7 @@ public BootstrapMethodArgumentEditPanel(Wrapper wrapper) { }); }); }}); - add(new JButton("Remove") {{ + add(new JButton(LangUtil.i18n("button.remove")) {{ addActionListener(e -> { if (objectJList.getSelectedIndex() != -1) { objectDefaultListModel.remove(objectJList.getSelectedIndex()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java index de5a096..4b34629 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.confirm; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.util.OpcodeUtil; import cn.enaium.joe.util.StringUtil; @@ -106,7 +107,7 @@ public ObjectList(List list) { }); }); }}); - add(new JButton("Remove") {{ + add(new JButton(LangUtil.i18n("button.remove")) {{ addActionListener(e -> { if (jList.getSelectedIndex() != -1) { stringDefaultListModel.remove(jList.getSelectedIndex()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java index f40c095..283167d 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/confirm/InstructionEditPanel.java @@ -17,7 +17,9 @@ package cn.enaium.joe.gui.panel.confirm; import cn.enaium.joe.gui.panel.instruction.*; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; +import cn.enaium.joe.util.OpcodeUtil; import org.objectweb.asm.tree.*; import java.awt.*; @@ -86,7 +88,7 @@ public InstructionEditPanel(AbstractInsnNode instruction) { setConfirm(() -> { try { if (!finalAbstractInstructionPanel.getConfirm().call()) { - MessageUtil.info("Failed"); + MessageUtil.info(LangUtil.i18n("fail")); } } catch (Exception ex) { MessageUtil.error(ex); diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java index 50d33ab..15869ad 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/confirm/LabelListEditPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.confirm; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.wrapper.LabelNodeWrapper; import cn.enaium.joe.wrapper.Wrapper; @@ -41,7 +42,7 @@ public LabelListEditPanel(List labelNodes, InsnList instructions) { } add(new JScrollPane(labelNodeWrapperJList), BorderLayout.CENTER); add(new JPanel() {{ - add(new JButton("Add") {{ + add(new JButton(LangUtil.i18n("button.add")) {{ addActionListener(e -> { DefaultComboBoxModel labelNodeWrapperDefaultComboBoxModel = new DefaultComboBoxModel<>(); JComboBox labelNodeWrapperJComboBox = new JComboBox<>(labelNodeWrapperDefaultComboBoxModel); @@ -58,7 +59,7 @@ public LabelListEditPanel(List labelNodes, InsnList instructions) { }); }); }}); - add(new JButton("Remove") {{ + add(new JButton(LangUtil.i18n("button.remove")) {{ addActionListener(e -> { if (labelNodeWrapperJList.getSelectedIndex() != -1) { labelNodeWrapperDefaultListModel.remove(labelNodeWrapperJList.getSelectedIndex()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java b/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java index a145684..298f320 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/confirm/LookupSwitchEditPanel.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.confirm; import cn.enaium.joe.gui.component.LabelNodeComboBox; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.wrapper.LabelNodeWrapper; import org.objectweb.asm.tree.LabelNode; @@ -46,7 +47,7 @@ public boolean isCellEditable(int row, int column) { } add(new JScrollPane(jTable), BorderLayout.CENTER); add(new JPanel() {{ - add(new JButton("Add") {{ + add(new JButton(LangUtil.i18n("button.add")) {{ addActionListener(e -> { MessageUtil.confirm(new ConfirmPanel() {{ JSpinner key = new JSpinner(); @@ -62,7 +63,7 @@ public boolean isCellEditable(int row, int column) { }}, "Add"); }); }}); - add(new JButton("Remove") {{ + add(new JButton(LangUtil.i18n("button.remove")) {{ addActionListener(e -> { if (jTable.getSelectedRow() != -1) { dm.removeRow(jTable.getSelectedRow()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java index ff71d6d..eb25582 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ASMifierTablePanel.java @@ -19,6 +19,7 @@ import cn.enaium.joe.JavaOctetEditor; import cn.enaium.joe.gui.panel.CodeAreaPanel; import cn.enaium.joe.util.ASyncUtil; +import cn.enaium.joe.util.LangUtil; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; @@ -80,7 +81,7 @@ public void keyPressed(KeyEvent e) { ClassNode newClassNode = new ClassNode(); new ClassReader(dumps).accept(newClassNode, ClassReader.EXPAND_FRAMES); JavaOctetEditor.getInstance().jar.classes.put(newClassNode.name + ".class", newClassNode); - JOptionPane.showMessageDialog(null, "Save Success"); + JOptionPane.showMessageDialog(null, LangUtil.i18n("success")); } catch (Throwable ex) { throw new RuntimeException(ex); } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java index 856d06a..d25b1df 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/ClassInfoTabPanel.java @@ -129,7 +129,7 @@ public ClassInfoTabPanel(ClassNode classNode) { classNode.outerClass = null; } - JOptionPane.showMessageDialog(ClassInfoTabPanel.this, "Save success"); + JOptionPane.showMessageDialog(ClassInfoTabPanel.this, LangUtil.i18n("success")); }); }}, BorderLayout.SOUTH); } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/FieldInfoPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/FieldInfoPanel.java index 60ab827..d456a2d 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/FieldInfoPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/FieldInfoPanel.java @@ -70,7 +70,7 @@ public FieldInfoPanel(FieldNode fieldNode) { fieldNode.signature = null; } - JOptionPane.showMessageDialog(FieldInfoPanel.this, "Save success"); + JOptionPane.showMessageDialog(FieldInfoPanel.this, LangUtil.i18n("success")); }); }}, BorderLayout.SOUTH); } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInfoTabPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInfoTabPanel.java index 837c588..6d8e520 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInfoTabPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInfoTabPanel.java @@ -81,7 +81,7 @@ public MethodInfoTabPanel(MethodNode methodNode) { methodNode.exceptions = new ArrayList<>(); } - JOptionPane.showMessageDialog(MethodInfoTabPanel.this, "Save success"); + JOptionPane.showMessageDialog(MethodInfoTabPanel.this, LangUtil.i18n("success")); }); }}, BorderLayout.SOUTH); } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstructionPanel.java index bf773ea..432503a 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstructionPanel.java @@ -16,15 +16,25 @@ package cn.enaium.joe.gui.panel.file.tabbed.tab.classes.method; +import cn.enaium.joe.gui.component.InstructionComboBox; import cn.enaium.joe.gui.panel.confirm.InstructionEditPanel; +import cn.enaium.joe.util.HtmlUtil; import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; +import cn.enaium.joe.util.OpcodeUtil; +import cn.enaium.joe.wrapper.InstructionWrapper; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.*; import javax.swing.*; import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.HashMap; /** * @author Enaium @@ -33,37 +43,99 @@ public class MethodInstructionPanel extends JPanel { public MethodInstructionPanel(MethodNode methodNode) { super(new BorderLayout()); - JList jList = new JList<>(new DefaultListModel<>()); + DefaultListModel instructionDefaultListModel = new DefaultListModel<>(); + JList instructionJList = new JList<>(instructionDefaultListModel); for (AbstractInsnNode instruction : methodNode.instructions) { - ((DefaultListModel) jList.getModel()).addElement(new MethodInstruction(methodNode.instructions.indexOf(instruction), instruction)); + instructionDefaultListModel.addElement(new InstructionWrapper(instruction)); } JPopupMenu jPopupMenu = new JPopupMenu(); - JMenuItem jMenuItem = new JMenuItem(LangUtil.i18n("instruction.edit")); - jMenuItem.addActionListener(e -> { - MethodInstruction selectedValue = jList.getSelectedValue(); - if (selectedValue != null && !(selectedValue.getInstruction() instanceof LabelNode)) { - MessageUtil.confirm(new InstructionEditPanel(selectedValue.getInstruction()), "Instruction Edit"); - } - }); - jPopupMenu.add(jMenuItem); + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instruction.edit")) {{ + addActionListener(e -> { + InstructionWrapper selectedValue = instructionJList.getSelectedValue(); + if (selectedValue != null && !(selectedValue.getWrapper() instanceof LabelNode)) { + MessageUtil.confirm(new InstructionEditPanel(selectedValue.getWrapper()), LangUtil.i18n("popup.instruction.edit")); + } + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instruction.clone")) {{ + addActionListener(e -> { + InstructionWrapper selectedValue = instructionJList.getSelectedValue(); + if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { + AbstractInsnNode clone; + if (selectedValue.getWrapper() instanceof LabelNode) { + clone = new LabelNode(); + } else { + clone = selectedValue.getWrapper().clone(new HashMap<>()); + } + + instructionDefaultListModel.add(instructionJList.getSelectedIndex() + 1, new InstructionWrapper(clone)); + methodNode.instructions.insert(selectedValue.getWrapper(), clone); + } + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.remove")) {{ + addActionListener(e -> { + InstructionWrapper selectedValue = instructionJList.getSelectedValue(); + if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { + MessageUtil.confirm(LangUtil.i18n("dialog.wantRemove"), LangUtil.i18n("button.remove"), () -> { + instructionDefaultListModel.remove(instructionJList.getSelectedIndex()); + methodNode.instructions.remove(selectedValue.getWrapper()); + }); + } + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.copyText")) {{ + addActionListener(e -> { + InstructionWrapper selectedValue = instructionJList.getSelectedValue(); + if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(HtmlUtil.remove(selectedValue.toString())), null); + } + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.insertBefore")) {{ + addActionListener(e -> { + insert(methodNode, instructionJList, true); + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.insertAfter")) {{ + addActionListener(e -> { + insert(methodNode, instructionJList, false); + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.moveUp")) {{ + addActionListener(e -> { + moveInstruction(instructionJList, methodNode, true); + }); + }}); + + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.instructions.moveDown")) {{ + addActionListener(e -> { + moveInstruction(instructionJList, methodNode, false); + }); + }}); - jList.addMouseListener(new MouseAdapter() { + instructionJList.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { - if (jList.getSelectedValue() != null) { - jPopupMenu.show(jList, e.getX(), e.getY()); + if (instructionJList.getSelectedValue() != null) { + jPopupMenu.show(instructionJList, e.getX(), e.getY()); } } } }); - add(new JScrollPane(jList), BorderLayout.CENTER); + add(new JScrollPane(instructionJList), BorderLayout.CENTER); JLabel comp = new JLabel(); - jList.addListSelectionListener(e -> { - if (jList.getSelectedValue() != null) { - MethodInstruction selectedValue = jList.getSelectedValue(); - comp.setText(String.format("Index:%d", selectedValue.getIndex())); + instructionJList.addListSelectionListener(e -> { + if (instructionJList.getSelectedIndex() != -1) { + comp.setText(String.format("Index:%d", instructionJList.getSelectedIndex())); comp.setVisible(true); } else { comp.setVisible(false); @@ -71,4 +143,102 @@ public void mouseReleased(MouseEvent e) { }); add(comp, BorderLayout.SOUTH); } + + private static void moveInstruction(JList instructionJList, MethodNode methodNode, boolean up) { + DefaultListModel instructionDefaultListModel = ((DefaultListModel) instructionJList.getModel()); + InstructionWrapper selectedValue = instructionJList.getSelectedValue(); + if (instructionJList.getSelectedIndex() != -1 || selectedValue != null) { + AbstractInsnNode node = up ? selectedValue.getWrapper().getPrevious() : selectedValue.getWrapper().getNext(); + if (node != null) { + try { + InstructionWrapper instructionWrapper = instructionDefaultListModel.get(instructionJList.getSelectedIndex() + (up ? -1 : 1)); + instructionDefaultListModel.removeElement(instructionWrapper); + instructionDefaultListModel.add(instructionJList.getSelectedIndex() + (up ? 1 : 0), instructionWrapper); + } catch (Exception ignore) { + + } + methodNode.instructions.remove(node); + if (up) { + methodNode.instructions.insert(selectedValue.getWrapper(), node); + } else { + methodNode.instructions.insertBefore(selectedValue.getWrapper(), node); + } + } + } + } + + private static void insert(MethodNode methodNode, JList instructionJList, boolean before) { + if (instructionJList.getSelectedIndex() == -1 || instructionJList.getSelectedValue() == null) { + return; + } + DefaultListModel instructionDefaultListModel = ((DefaultListModel) instructionJList.getModel()); + InstructionComboBox instructionComboBox = new InstructionComboBox(); + MessageUtil.confirm(instructionComboBox, "select insert instruction", () -> { + AbstractInsnNode abstractInsnNode; + int selectedIndex = instructionComboBox.getSelectedIndex(); + switch (selectedIndex) { + case AbstractInsnNode.INSN: + abstractInsnNode = new InsnNode(Opcodes.NOP); + break; + case AbstractInsnNode.INT_INSN: + abstractInsnNode = new IntInsnNode(Opcodes.BIPUSH, 0); + break; + case AbstractInsnNode.VAR_INSN: + abstractInsnNode = new VarInsnNode(Opcodes.ILOAD, 0); + break; + case AbstractInsnNode.TYPE_INSN: + abstractInsnNode = new TypeInsnNode(Opcodes.ILOAD, ""); + break; + case AbstractInsnNode.FIELD_INSN: + abstractInsnNode = new FieldInsnNode(Opcodes.GETSTATIC, "", "", ""); + break; + case AbstractInsnNode.METHOD_INSN: + abstractInsnNode = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "", "", "", false); + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + abstractInsnNode = new InvokeDynamicInsnNode("", "", new Handle(Opcodes.H_GETFIELD, "", "", "", false)); + break; + case AbstractInsnNode.JUMP_INSN: + abstractInsnNode = new JumpInsnNode(Opcodes.IFEQ, OpcodeUtil.getFirstLabel(methodNode.instructions)); + break; + case AbstractInsnNode.LABEL: + abstractInsnNode = new LabelNode(); + break; + case AbstractInsnNode.LDC_INSN: + abstractInsnNode = new LdcInsnNode(""); + break; + case AbstractInsnNode.IINC_INSN: + abstractInsnNode = new IntInsnNode(Opcodes.IINC, 0); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + abstractInsnNode = new TableSwitchInsnNode(0, 0, OpcodeUtil.getFirstLabel(methodNode.instructions)); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + abstractInsnNode = new LookupSwitchInsnNode(OpcodeUtil.getFirstLabel(methodNode.instructions), new int[]{}, new LabelNode[]{}); + break; + case AbstractInsnNode.MULTIANEWARRAY_INSN: + abstractInsnNode = new MultiANewArrayInsnNode("", 0); + break; + case AbstractInsnNode.FRAME: + abstractInsnNode = new FrameNode(Opcodes.F_NEW, 0, new Object[]{}, 0, new Object[]{}); + break; + case AbstractInsnNode.LINE: + abstractInsnNode = new LineNumberNode(0, OpcodeUtil.getFirstLabel(methodNode.instructions)); + break; + default: + throw new RuntimeException(); + } + + InstructionEditPanel message = new InstructionEditPanel(abstractInsnNode); + MessageUtil.confirm(message, LangUtil.i18n("popup.instruction.edit"), () -> { + message.getConfirm().run(); + if (before) { + methodNode.instructions.insertBefore(instructionJList.getSelectedValue().getWrapper(), abstractInsnNode); + } else { + methodNode.instructions.insert(instructionJList.getSelectedValue().getWrapper(), abstractInsnNode); + } + instructionDefaultListModel.add(instructionJList.getSelectedIndex() + (before ? 0 : 1), new InstructionWrapper(abstractInsnNode)); + }); + }); + } } diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreePanel.java b/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreePanel.java index 32859fe..2d78201 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreePanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/file/tree/FileTreePanel.java @@ -27,6 +27,7 @@ import cn.enaium.joe.jar.Jar; import cn.enaium.joe.util.ASyncUtil; import cn.enaium.joe.util.JTreeUtil; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; @@ -101,7 +102,7 @@ public FileTreePanel() { JPopupMenu jPopupMenu = new JPopupMenu(); - jPopupMenu.add(new JMenuItem("Expand all") {{ + jPopupMenu.add(new JMenuItem(LangUtil.i18n("popup.expandAll")) {{ addActionListener(e -> { JTreeUtil.setNodeExpandedState(FileTreePanel.this, ((DefaultMutableTreeNode) Objects.requireNonNull(getSelectionPath()).getLastPathComponent()), true); }); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java index bddffa9..fd1805d 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/AbstractInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.OpcodeUtil; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; @@ -45,7 +46,7 @@ public AbstractInstructionPanel(AbstractInsnNode instruction) { DefaultComboBoxModel model = (DefaultComboBoxModel) opcode.getModel(); getOpcodes().forEach(model::addElement); model.setSelectedItem(OpcodeUtil.OPCODE.get(instruction.getOpcode())); - addComponent(new JLabel("Opcode:"), opcode); + addComponent(new JLabel(LangUtil.i18n("instruction.opcode")), opcode); } add(names, BorderLayout.WEST); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java index faefba8..f986ec1 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/FieldInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.TypeInsnNode; @@ -34,9 +35,9 @@ public FieldInstructionPanel(FieldInsnNode instruction) { JTextField owner = new JTextField(instruction.owner); JTextField name = new JTextField(instruction.name); JTextField description = new JTextField(instruction.desc); - addComponent(new JLabel("Owner:"), owner); - addComponent(new JLabel("Name:"), name); - addComponent(new JLabel("Description:"), description); + addComponent(new JLabel(LangUtil.i18n("instruction.owner")), owner); + addComponent(new JLabel(LangUtil.i18n("instruction.name")), name); + addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); setConfirm(() -> { instruction.setOpcode(getOpcode()); instruction.owner = owner.getText(); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java index f990005..6c02c23 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/FrameInstructionPanel.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.instruction; import cn.enaium.joe.gui.panel.confirm.FrameListEditPanel; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.util.OpcodeUtil; import org.objectweb.asm.tree.FrameNode; @@ -34,8 +35,8 @@ public FrameInstructionPanel(FrameNode instruction) { super(instruction); JComboBox component = new JComboBox<>(OpcodeUtil.FRAME.values().toArray(new String[0])); component.setSelectedItem(OpcodeUtil.FRAME.get(instruction.type)); - addComponent(new JLabel("Type:"), component); - addComponent(new JLabel("Local/Stack:"), new JButton("Edit") {{ + addComponent(new JLabel(LangUtil.i18n("instruction.type")), component); + addComponent(new JLabel(LangUtil.i18n("instruction.localOrStack")), new JButton(LangUtil.i18n("button.edit")) {{ addActionListener(e -> { FrameListEditPanel frameListEditPanel = new FrameListEditPanel(instruction); MessageUtil.confirm(frameListEditPanel, "Frame Edit", () -> { diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java index 06134c9..33410a4 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/IncrInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.IincInsnNode; import org.objectweb.asm.tree.InsnList; @@ -33,10 +34,10 @@ public IncrInstructionPanel(IincInsnNode instruction) { super(instruction); JSpinner varIndex = new JSpinner(); varIndex.setValue(instruction.var); - addComponent(new JLabel("Var Index:"), varIndex); + addComponent(new JLabel(LangUtil.i18n("instruction.varIndex")), varIndex); JSpinner incr = new JSpinner(); incr.setValue(instruction.incr); - addComponent(new JLabel("Incr:"), incr); + addComponent(new JLabel(LangUtil.i18n("instruction.incr")), incr); setConfirm(() -> { instruction.var = Integer.parseInt(varIndex.getValue().toString()); instruction.incr = Integer.parseInt(incr.getValue().toString()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java index d768f46..38ed1e1 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/IntInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.InsnNode; @@ -34,7 +35,7 @@ public IntInstructionPanel(IntInsnNode instruction) { super(instruction); JSpinner operand = new JSpinner(); operand.setValue(instruction.operand); - addComponent(new JLabel("Operand:"), operand); + addComponent(new JLabel(LangUtil.i18n("instruction.operand")), operand); setConfirm(() -> { instruction.setOpcode(getOpcode()); instruction.operand = Integer.parseInt(operand.getValue().toString()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java index dcb3bc4..47de3a7 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/InvokeDynamicInstructionPanel.java @@ -18,6 +18,7 @@ import cn.enaium.joe.gui.panel.confirm.BootstrapMethodArgumentEditPanel; import cn.enaium.joe.gui.panel.confirm.HandleEditPanel; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.wrapper.Wrapper; import org.objectweb.asm.Handle; @@ -36,9 +37,9 @@ public InvokeDynamicInstructionPanel(InvokeDynamicInsnNode instruction) { super(instruction); JTextField name = new JTextField(instruction.name); JTextField description = new JTextField(instruction.desc); - addComponent(new JLabel("Name:"), name); - addComponent(new JLabel("Description:"), description); - addComponent(new JLabel("Bootstrap Method:"), new JButton("Edit") {{ + addComponent(new JLabel(LangUtil.i18n("instruction.name")), name); + addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); + addComponent(new JLabel(LangUtil.i18n("instruction.bootstrapMethod")), new JButton(LangUtil.i18n("button.edit")) {{ addActionListener(e -> { Wrapper wrapper = new Wrapper<>(instruction.bsm); HandleEditPanel handleEditPanel = new HandleEditPanel(wrapper); @@ -50,11 +51,11 @@ public InvokeDynamicInstructionPanel(InvokeDynamicInsnNode instruction) { }); }); }}); - addComponent(new JLabel("Bootstrap Method Argument:"), new JButton("Edit") {{ + addComponent(new JLabel(LangUtil.i18n("instruction.bootstrapMethodArgument")), new JButton(LangUtil.i18n("button.edit")) {{ addActionListener(e -> { Wrapper bsmArgs = new Wrapper<>(instruction.bsmArgs); BootstrapMethodArgumentEditPanel confirmPanel = new BootstrapMethodArgumentEditPanel(bsmArgs); - MessageUtil.confirm(confirmPanel, "Bootstrap method argument", () -> { + MessageUtil.confirm(confirmPanel, LangUtil.i18n("instruction.bootstrapMethodArgument"), () -> { confirmPanel.getConfirm().run(); instruction.bsmArgs = bsmArgs.getWrapper(); }, () -> { diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java index 8275e1f..d94dafa 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/JumpInstructionPanel.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.instruction; import cn.enaium.joe.gui.component.LabelNodeComboBox; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.OpcodeUtil; import cn.enaium.joe.wrapper.LabelNodeWrapper; import org.objectweb.asm.tree.*; @@ -33,7 +34,7 @@ public class JumpInstructionPanel extends AbstractInstructionPanel { public JumpInstructionPanel(JumpInsnNode instruction) { super(instruction); LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.label); - addComponent(new JLabel("Label:"), component); + addComponent(new JLabel(LangUtil.i18n("instruction.label")), component); setConfirm(() -> { Object selectedItem = component.getSelectedItem(); if (selectedItem != null) { diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java index d04a9c6..bfd1e69 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/LdcInstructionPanel.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.instruction; import cn.enaium.joe.gui.panel.confirm.HandleEditPanel; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.wrapper.Wrapper; import org.objectweb.asm.Handle; @@ -26,9 +27,12 @@ import org.objectweb.asm.tree.VarInsnNode; import javax.swing.*; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; /** * @author Enaium @@ -57,52 +61,79 @@ public LdcInstructionPanel(LdcInsnNode instruction) { handle = ((Handle) instruction.cst); } - if (handle == null) { - JTextField ldc = new JTextField(); - ldc.setText(instruction.cst.toString()); - addComponent(new JLabel("Var:"), ldc); - setConfirm(() -> { - Object value; - if (jComboBox.getSelectedItem() != null) { - switch (jComboBox.getSelectedItem().toString()) { - case "String": - value = ldc.getText(); - break; - case "float": - value = Float.parseFloat(ldc.getText()); - break; - case "double": - value = Double.parseDouble(ldc.getText()); - break; - case "int": - value = Integer.parseInt(ldc.getText()); - break; - case "long": - value = Long.parseLong(ldc.getText()); - break; - case "Class": - value = Type.getType(ldc.getText()); - break; - default: - return false; - } - instruction.cst = value; + JTextField ldc = new JTextField(); + ldc.setText(instruction.cst.toString()); + JLabel verLabel = new JLabel(LangUtil.i18n("instruction.var")); + verLabel.setVisible(!(Objects.equals(jComboBox.getSelectedItem(), "Handle"))); + ldc.setVisible(!(Objects.equals(jComboBox.getSelectedItem(), "Handle"))); + addComponent(verLabel, ldc); + setConfirm(() -> { + Object value; + if (jComboBox.getSelectedItem() != null) { + switch (jComboBox.getSelectedItem().toString()) { + case "String": + value = ldc.getText(); + break; + case "float": + value = Float.parseFloat(ldc.getText()); + break; + case "double": + value = Double.parseDouble(ldc.getText()); + break; + case "int": + value = Integer.parseInt(ldc.getText()); + break; + case "long": + value = Long.parseLong(ldc.getText()); + break; + case "Class": + value = Type.getType(ldc.getText()); + break; + default: + return true; } - return true; - }); - } else { - Handle finalHandle = handle; - addComponent(new JLabel("Handle"), new JButton("Edit") {{ + instruction.cst = value; + } + return true; + }); + Handle finalHandle = handle; + + JLabel handleLabel = new JLabel(LangUtil.i18n("instruction.handle")); + handleLabel.setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); + JButton handleButton = new JButton(LangUtil.i18n("button.edit")) {{ + setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); + addActionListener(e -> { Wrapper wrapper = new Wrapper<>(finalHandle); HandleEditPanel message = new HandleEditPanel(wrapper); - MessageUtil.confirm(message, "Handle Edit", () -> { + MessageUtil.confirm(message, LangUtil.i18n("instruction.handle"), () -> { message.getConfirm().run(); instruction.cst = wrapper.getWrapper(); }, () -> { }); - }}); - setConfirm(() -> true); - } + }); + }}; + addComponent(handleLabel, handleButton); + jComboBox.getModel().addListDataListener(new ListDataListener() { + @Override + public void intervalAdded(ListDataEvent e) { + + } + + @Override + public void intervalRemoved(ListDataEvent e) { + + } + + @Override + public void contentsChanged(ListDataEvent e) { + System.out.println("Change"); + handleLabel.setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); + handleButton.setVisible(Objects.equals(jComboBox.getSelectedItem(), "Handle")); + verLabel.setVisible(!Objects.equals(jComboBox.getSelectedItem(), "Handle")); + ldc.setVisible(!Objects.equals(jComboBox.getSelectedItem(), "Handle")); + } + }); + } @Override diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java index 80f78ca..7e69321 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/LineInstructionPanel.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.instruction; import cn.enaium.joe.gui.component.LabelNodeComboBox; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.OpcodeUtil; import cn.enaium.joe.wrapper.LabelNodeWrapper; import org.objectweb.asm.tree.*; @@ -36,9 +37,9 @@ public LineInstructionPanel(LineNumberNode instruction) { super(instruction); JSpinner spinner = new JSpinner(); spinner.setValue(instruction.line); - addComponent(new JLabel("Line:"), spinner); + addComponent(new JLabel(LangUtil.i18n("instruction.line")), spinner); LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.start); - addComponent(new JLabel("Start:"), component); + addComponent(new JLabel(LangUtil.i18n("instruction.start")), component); setConfirm(() -> { Object selectedItem = component.getSelectedItem(); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java index 2fc9a47..fbeb873 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/LookupSwitchInstructionPanel.java @@ -18,6 +18,7 @@ import cn.enaium.joe.gui.component.LabelNodeComboBox; import cn.enaium.joe.gui.panel.confirm.LookupSwitchEditPanel; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.util.OpcodeUtil; import cn.enaium.joe.wrapper.LabelNodeWrapper; @@ -38,10 +39,10 @@ public class LookupSwitchInstructionPanel extends AbstractInstructionPanel { public LookupSwitchInstructionPanel(LookupSwitchInsnNode instruction) { super(instruction); LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.dflt); - addComponent(new JLabel("Default:"), component); - addComponent(new JLabel("Keys/Labels"), new JButton("Edit") {{ + addComponent(new JLabel(LangUtil.i18n("instruction.default")), component); + addComponent(new JLabel(LangUtil.i18n("instruction.keyOrLabel")), new JButton(LangUtil.i18n("button.edit")) {{ addActionListener(e -> { - MessageUtil.confirm(new LookupSwitchEditPanel(instruction.keys, instruction.labels), "Keys/Labels"); + MessageUtil.confirm(new LookupSwitchEditPanel(instruction.keys, instruction.labels), LangUtil.i18n("instruction.keyOrLabel")); }); }}); setConfirm(() -> { diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java index 6f58220..f872973 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/MethodInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodInsnNode; @@ -37,10 +38,10 @@ public MethodInstructionPanel(MethodInsnNode instruction) { JCheckBox isInterface = new JCheckBox() {{ setHorizontalAlignment(JCheckBox.RIGHT); }}; - addComponent(new JLabel("Owner:"), owner); - addComponent(new JLabel("Name:"), name); - addComponent(new JLabel("Description:"), description); - addComponent(new JLabel("Interface:"), isInterface); + addComponent(new JLabel(LangUtil.i18n("instruction.owner")), owner); + addComponent(new JLabel(LangUtil.i18n("instruction.name")), name); + addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); + addComponent(new JLabel(LangUtil.i18n("instruction.interface")), isInterface); setConfirm(() -> { instruction.setOpcode(getOpcode()); instruction.owner = owner.getText(); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java index 40b0ffa..317eeb0 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/MultiANewArrayInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MultiANewArrayInsnNode; @@ -33,10 +34,10 @@ public MultiANewArrayInstructionPanel(MultiANewArrayInsnNode instruction) { super(instruction); JTextField description = new JTextField(); description.setText(instruction.desc); - addComponent(new JLabel("Description"), description); + addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); JSpinner dimension = new JSpinner(); dimension.setValue(instruction.dims); - addComponent(new JLabel("Dimension"), dimension); + addComponent(new JLabel(LangUtil.i18n("instruction.dimension")), dimension); setConfirm(() -> { instruction.desc = description.getText(); instruction.dims = Integer.parseInt(dimension.getValue().toString()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java index a096d96..f74a1d9 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/TableSwitchInstructionPanel.java @@ -18,6 +18,7 @@ import cn.enaium.joe.gui.component.LabelNodeComboBox; import cn.enaium.joe.gui.panel.confirm.LabelListEditPanel; +import cn.enaium.joe.util.LangUtil; import cn.enaium.joe.util.MessageUtil; import cn.enaium.joe.util.OpcodeUtil; import cn.enaium.joe.wrapper.LabelNodeWrapper; @@ -38,13 +39,13 @@ public TableSwitchInstructionPanel(TableSwitchInsnNode instruction) { super(instruction); JSpinner min = new JSpinner(); min.setValue(instruction.min); - addComponent(new JLabel("Min:"), min); + addComponent(new JLabel(LangUtil.i18n("instruction.min")), min); JSpinner max = new JSpinner(); max.setValue(instruction.max); - addComponent(new JLabel("Max:"), max); + addComponent(new JLabel(LangUtil.i18n("instruction.max")), max); LabelNodeComboBox component = new LabelNodeComboBox(instruction, instruction.dflt); - addComponent(new JLabel("Default:"), component); - addComponent(new JLabel("Labels:"), new JButton("Edit") {{ + addComponent(new JLabel(LangUtil.i18n("instruction.default")), component); + addComponent(new JLabel(LangUtil.i18n("instruction.labels")), new JButton(LangUtil.i18n("button.edit")) {{ addActionListener(e -> { MessageUtil.confirm(new LabelListEditPanel(instruction.labels, OpcodeUtil.getInstructionList(instruction)), "Labels Edit"); }); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java index 4b2ac66..eedcc90 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/TypeInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.TypeInsnNode; @@ -32,7 +33,7 @@ public class TypeInstructionPanel extends AbstractInstructionPanel { public TypeInstructionPanel(TypeInsnNode instruction) { super(instruction); JTextField description = new JTextField(instruction.desc); - addComponent(new JLabel("Description:"), description); + addComponent(new JLabel(LangUtil.i18n("instruction.description")), description); setConfirm(() -> { instruction.setOpcode(getOpcode()); instruction.desc = description.getText(); diff --git a/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java b/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java index ed6ca4b..f6ada76 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java +++ b/src/main/java/cn/enaium/joe/gui/panel/instruction/VarInstructionPanel.java @@ -16,6 +16,7 @@ package cn.enaium.joe.gui.panel.instruction; +import cn.enaium.joe.util.LangUtil; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.IntInsnNode; @@ -34,7 +35,7 @@ public VarInstructionPanel(VarInsnNode instruction) { super(instruction); JSpinner spinner = new JSpinner(); spinner.setValue(instruction.var); - addComponent(new JLabel("Var:"), spinner); + addComponent(new JLabel(LangUtil.i18n("instruction.var")), spinner); setConfirm(() -> { instruction.setOpcode(getOpcode()); instruction.var = Integer.parseInt(spinner.getValue().toString()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java index d5ab7b2..d48bdbf 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java +++ b/src/main/java/cn/enaium/joe/gui/panel/menu/FileMenu.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.menu; import cn.enaium.joe.gui.panel.menu.file.LoadMenuItem; +import cn.enaium.joe.gui.panel.menu.file.LoadRecentMenu; import cn.enaium.joe.gui.panel.menu.file.SaveAllSourceMenuItem; import cn.enaium.joe.gui.panel.menu.file.SaveMenuItem; import cn.enaium.joe.util.LangUtil; @@ -30,6 +31,7 @@ public class FileMenu extends JMenu { public FileMenu() { super(LangUtil.i18n("menu.file")); add(new LoadMenuItem()); + add(new LoadRecentMenu()); add(new SaveMenuItem()); add(new JSeparator()); add(new SaveAllSourceMenuItem()); diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java index 981d8b2..105ec4c 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java +++ b/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadMenuItem.java @@ -17,6 +17,7 @@ package cn.enaium.joe.gui.panel.menu.file; import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.config.extend.ApplicationConfig; import cn.enaium.joe.jar.Jar; import cn.enaium.joe.util.ASyncUtil; import cn.enaium.joe.util.JFileChooserUtil; diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadRecentMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadRecentMenu.java new file mode 100644 index 0000000..7588359 --- /dev/null +++ b/src/main/java/cn/enaium/joe/gui/panel/menu/file/LoadRecentMenu.java @@ -0,0 +1,64 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.gui.panel.menu.file; + +import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.config.extend.ApplicationConfig; +import cn.enaium.joe.jar.Jar; +import cn.enaium.joe.util.ASyncUtil; +import cn.enaium.joe.util.LangUtil; + +import javax.swing.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.util.Set; + +/** + * @author Enaium + * @since 0.9.0 + */ +public class LoadRecentMenu extends JMenuItem { + public LoadRecentMenu() { + super(LangUtil.i18n("menu.file.loadRecent")); + addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + JPopupMenu jPopupMenu = new JPopupMenu(); + Set loadRecent = JavaOctetEditor.getInstance().configManager.getByClass(ApplicationConfig.class).loadRecent.getValue(); + for (String s : loadRecent) { + jPopupMenu.add(new JMenuItem(s) {{ + addActionListener(e -> { + System.out.println(s); + File file = new File(s); + if (file.exists()) { + ASyncUtil.execute(() -> { + Jar jar = new Jar(); + jar.load(file); + JavaOctetEditor.getInstance().fileTreePanel.refresh(jar); + }); + } else { + loadRecent.remove(s); + } + }); + }}); + } + jPopupMenu.show(JavaOctetEditor.getInstance().fileTreePanel, e.getX(), e.getY()); + } + }); + } +} diff --git a/src/main/java/cn/enaium/joe/jar/Jar.java b/src/main/java/cn/enaium/joe/jar/Jar.java index eaad5e9..43f9f68 100644 --- a/src/main/java/cn/enaium/joe/jar/Jar.java +++ b/src/main/java/cn/enaium/joe/jar/Jar.java @@ -17,6 +17,7 @@ package cn.enaium.joe.jar; import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.config.extend.ApplicationConfig; import cn.enaium.joe.util.Util; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; @@ -39,6 +40,7 @@ public class Jar { public Map resources = new LinkedHashMap<>(); public void load(File file) { + JavaOctetEditor.getInstance().configManager.getByClass(ApplicationConfig.class).loadRecent.getValue().add(file.getAbsolutePath()); JavaOctetEditor.getInstance().jar = this; JavaOctetEditor.getInstance().window.setTitle(JavaOctetEditor.TITLE + "-" + file.getName()); try { diff --git a/src/main/java/cn/enaium/joe/util/HtmlUtil.java b/src/main/java/cn/enaium/joe/util/HtmlUtil.java index de9c01a..9ae2f35 100644 --- a/src/main/java/cn/enaium/joe/util/HtmlUtil.java +++ b/src/main/java/cn/enaium/joe/util/HtmlUtil.java @@ -17,6 +17,8 @@ package cn.enaium.joe.util; import java.awt.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author Enaium @@ -30,4 +32,8 @@ public static String toHtml(String text) { public static String setColor(String text, Color color) { return String.format("%s", color.getRed(), color.getGreen(), color.getBlue(), text); } + + public static String remove(String text) { + return text.replaceAll("<[^>]+>",""); + } } diff --git a/src/main/java/cn/enaium/joe/util/IOUtil.java b/src/main/java/cn/enaium/joe/util/IOUtil.java new file mode 100644 index 0000000..922db38 --- /dev/null +++ b/src/main/java/cn/enaium/joe/util/IOUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * @author Enaium + * @since 0.9.0 + */ +public class IOUtil { + public static String getString(InputStream inputStream) throws IOException { + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line; + while ((line = bufferedReader.readLine()) != null) { + stringBuilder.append(line).append("\n"); + } + String text = stringBuilder.toString(); + inputStream.close(); + return stringBuilder.toString(); + } +} diff --git a/src/main/java/cn/enaium/joe/util/LangUtil.java b/src/main/java/cn/enaium/joe/util/LangUtil.java index 7a82a69..24f748a 100644 --- a/src/main/java/cn/enaium/joe/util/LangUtil.java +++ b/src/main/java/cn/enaium/joe/util/LangUtil.java @@ -41,30 +41,27 @@ public static String i18n(String key, Object... args) { lang = language.getValue(); } try { + + String en = IOUtil.getString(LangUtil.class.getResourceAsStream("/lang/en_US.json")); + URL url = LangUtil.class.getResource("/lang/" + lang + ".json"); - if (url == null) { - url = LangUtil.class.getResource("/lang/en_US.json"); - } if (url == null) { - RuntimeException runtimeException = new RuntimeException("Lang not Found!"); + RuntimeException runtimeException = new RuntimeException(String.format("lang ' %s ' not Found!", lang)); MessageUtil.error(runtimeException); throw runtimeException; } - InputStream inputStream = url.openStream(); - StringBuilder stringBuilder = new StringBuilder(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); - String line; - while ((line = bufferedReader.readLine()) != null) { - stringBuilder.append(line).append("\n"); - } - String text = stringBuilder.toString(); - inputStream.close(); - JsonObject jsonObject = new Gson().fromJson(text, JsonObject.class); + + JsonObject jsonObject = new Gson().fromJson(IOUtil.getString(url.openStream()), JsonObject.class); try { return String.format(jsonObject.get(key).getAsString(), args); } catch (NullPointerException e) { - MessageUtil.error(new NullPointerException(String.format("Lang not found \" %s \"", key))); + Logger.warn(String.format("Lang not found \" %s \" ", key)); + try { + return String.format(new Gson().fromJson(en, JsonObject.class).get(key).getAsString(), args); + } catch (NullPointerException ex) { + MessageUtil.error(new NullPointerException(String.format("not found key ' %s ' in en_us", key))); + } } } catch (IOException e) { MessageUtil.error(e); diff --git a/src/main/java/cn/enaium/joe/util/MessageUtil.java b/src/main/java/cn/enaium/joe/util/MessageUtil.java index bbf44f0..0853acc 100644 --- a/src/main/java/cn/enaium/joe/util/MessageUtil.java +++ b/src/main/java/cn/enaium/joe/util/MessageUtil.java @@ -29,15 +29,19 @@ public class MessageUtil { public static void error(Throwable e) { Logger.error(e); - JOptionPane.showMessageDialog(null, e.getMessage(), "ERROR", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, e.getMessage(), LangUtil.i18n("error"), JOptionPane.ERROR_MESSAGE); } public static void confirm(Object message, String title, Runnable yes, Runnable no) { int i = JOptionPane.showConfirmDialog(null, message, title, JOptionPane.OK_CANCEL_OPTION); if (i == JOptionPane.YES_OPTION) { - yes.run(); + if (yes != null) { + yes.run(); + } } else { - no.run(); + if (no != null) { + no.run(); + } } } @@ -49,11 +53,16 @@ public static void confirm(ConfirmPanel confirmPanel, String title) { }); } + public static void confirm(Object message, String title, Runnable yes) { + confirm(message, title, yes, null); + } + + public static void info(String message) { - JOptionPane.showMessageDialog(null, message, "INFO", JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(null, message, LangUtil.i18n("info"), JOptionPane.INFORMATION_MESSAGE); } public static void warning(String message) { - JOptionPane.showMessageDialog(null, message, "WARNING", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(null, message, LangUtil.i18n("warning"), JOptionPane.WARNING_MESSAGE); } } diff --git a/src/main/java/cn/enaium/joe/util/OpcodeUtil.java b/src/main/java/cn/enaium/joe/util/OpcodeUtil.java index 7e301b1..1b18c3c 100644 --- a/src/main/java/cn/enaium/joe/util/OpcodeUtil.java +++ b/src/main/java/cn/enaium/joe/util/OpcodeUtil.java @@ -283,6 +283,15 @@ public static InsnList getInstructionList(AbstractInsnNode abstractInsnNode) { return insnList; } + public static LabelNode getFirstLabel(InsnList instructions) { + for (AbstractInsnNode instruction : instructions) { + if (instruction instanceof LabelNode) { + return (LabelNode) instruction; + } + } + return null; + } + public static Map reverse(Map map) { Map reverseMap = new HashMap<>(); for (Map.Entry kvEntry : map.entrySet()) { diff --git a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstruction.java b/src/main/java/cn/enaium/joe/wrapper/InstructionWrapper.java similarity index 85% rename from src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstruction.java rename to src/main/java/cn/enaium/joe/wrapper/InstructionWrapper.java index 148006a..75c4c9a 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/classes/method/MethodInstruction.java +++ b/src/main/java/cn/enaium/joe/wrapper/InstructionWrapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.enaium.joe.gui.panel.file.tabbed.tab.classes.method; +package cn.enaium.joe.wrapper; import cn.enaium.joe.util.HtmlUtil; import cn.enaium.joe.util.OpcodeUtil; @@ -28,21 +28,11 @@ * @author Enaium * @since 0.8.0 */ -public class MethodInstruction { - private final int index; - private final AbstractInsnNode instruction; +public class InstructionWrapper extends Wrapper { - public MethodInstruction(int index, AbstractInsnNode instruction) { - this.index = index; - this.instruction = instruction; - } - - public int getIndex() { - return index; - } - public AbstractInsnNode getInstruction() { - return instruction; + public InstructionWrapper(AbstractInsnNode wrapper) { + super(wrapper); } @Override @@ -50,37 +40,37 @@ public String toString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(""); - if (instruction.getOpcode() != -1) { - stringBuilder.append(HtmlUtil.setColor(OpcodeUtil.OPCODE.get(instruction.getOpcode()), FontColor.opcode)); + if (getWrapper().getOpcode() != -1) { + stringBuilder.append(HtmlUtil.setColor(OpcodeUtil.OPCODE.get(getWrapper().getOpcode()), FontColor.opcode)); } - switch (instruction.getType()) { + switch (getWrapper().getType()) { case AbstractInsnNode.INSN: //Opcode break; case AbstractInsnNode.INT_INSN: - IntInsnNode intInsnNode = (IntInsnNode) instruction; + IntInsnNode intInsnNode = (IntInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(String.valueOf(intInsnNode.operand), FontColor.base)); break; case AbstractInsnNode.VAR_INSN: - append(stringBuilder, HtmlUtil.setColor(String.valueOf(((VarInsnNode) instruction).var), FontColor.base)); + append(stringBuilder, HtmlUtil.setColor(String.valueOf(((VarInsnNode) getWrapper()).var), FontColor.base)); break; case AbstractInsnNode.TYPE_INSN: - append(stringBuilder, HtmlUtil.setColor(((TypeInsnNode) instruction).desc, FontColor.desc)); + append(stringBuilder, HtmlUtil.setColor(((TypeInsnNode) getWrapper()).desc, FontColor.desc)); break; case AbstractInsnNode.FIELD_INSN: - FieldInsnNode fieldInsnNode = (FieldInsnNode) instruction; + FieldInsnNode fieldInsnNode = (FieldInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(fieldInsnNode.name, FontColor.name)); append(stringBuilder, HtmlUtil.setColor(fieldInsnNode.desc, FontColor.desc)); break; case AbstractInsnNode.METHOD_INSN: - MethodInsnNode methodInsnNode = (MethodInsnNode) instruction; + MethodInsnNode methodInsnNode = (MethodInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(methodInsnNode.name, FontColor.name)); append(stringBuilder, HtmlUtil.setColor(methodInsnNode.desc, FontColor.desc)); append(stringBuilder, HtmlUtil.setColor(String.valueOf(methodInsnNode.itf), FontColor.bool)); break; case AbstractInsnNode.INVOKE_DYNAMIC_INSN: - InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) instruction; + InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(invokeDynamicInsnNode.name, FontColor.name)); append(stringBuilder, HtmlUtil.setColor(invokeDynamicInsnNode.desc, FontColor.desc)); append(stringBuilder, "\n"); @@ -95,14 +85,14 @@ public String toString() { append(stringBuilder, HtmlUtil.setColor(Arrays.toString(strings), FontColor.desc)); break; case AbstractInsnNode.JUMP_INSN: - append(stringBuilder, HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(((JumpInsnNode) instruction).label), FontColor.base)); + append(stringBuilder, HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(((JumpInsnNode) getWrapper()).label), FontColor.base)); break; case AbstractInsnNode.LABEL: append(stringBuilder, HtmlUtil.setColor("L", FontColor.opcode)); - append(stringBuilder, HtmlUtil.setColor(String.valueOf(OpcodeUtil.getLabelIndex(instruction)), FontColor.base)); + append(stringBuilder, HtmlUtil.setColor(String.valueOf(OpcodeUtil.getLabelIndex(getWrapper())), FontColor.base)); break; case AbstractInsnNode.LDC_INSN: - LdcInsnNode ldcInsnNode = (LdcInsnNode) instruction; + LdcInsnNode ldcInsnNode = (LdcInsnNode) getWrapper(); if (ldcInsnNode.cst instanceof String) { append(stringBuilder, HtmlUtil.setColor("\"" + ldcInsnNode.cst + "\"", FontColor.string)); } else if (ldcInsnNode.cst instanceof Boolean) { @@ -112,12 +102,12 @@ public String toString() { } break; case AbstractInsnNode.IINC_INSN: - IincInsnNode iincInsnNode = (IincInsnNode) instruction; + IincInsnNode iincInsnNode = (IincInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(String.valueOf(iincInsnNode.var), FontColor.base)); append(stringBuilder, HtmlUtil.setColor(String.valueOf(iincInsnNode.incr), FontColor.base)); break; case AbstractInsnNode.TABLESWITCH_INSN: - TableSwitchInsnNode tableSwitchInsnNode = (TableSwitchInsnNode) instruction; + TableSwitchInsnNode tableSwitchInsnNode = (TableSwitchInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(String.format("range[%s:%s]", tableSwitchInsnNode.min, tableSwitchInsnNode.max), FontColor.desc)); tableSwitchInsnNode.labels.stream().map(OpcodeUtil::getLabelIndex).forEach(it -> append(stringBuilder, HtmlUtil.setColor("L" + it, FontColor.base))); if (tableSwitchInsnNode.dflt != null) { @@ -125,7 +115,7 @@ public String toString() { } break; case AbstractInsnNode.LOOKUPSWITCH_INSN: - LookupSwitchInsnNode lookupSwitchInsnNode = (LookupSwitchInsnNode) instruction; + LookupSwitchInsnNode lookupSwitchInsnNode = (LookupSwitchInsnNode) getWrapper(); for (int i = 0; i < lookupSwitchInsnNode.keys.size(); i++) { append(stringBuilder, HtmlUtil.setColor(String.valueOf(lookupSwitchInsnNode.keys.get(i)), FontColor.base) + ":" + HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(lookupSwitchInsnNode.labels.get(i)), FontColor.base)); } @@ -134,18 +124,18 @@ public String toString() { } break; case AbstractInsnNode.MULTIANEWARRAY_INSN: - MultiANewArrayInsnNode multiANewArrayInsnNode = (MultiANewArrayInsnNode) instruction; + MultiANewArrayInsnNode multiANewArrayInsnNode = (MultiANewArrayInsnNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(multiANewArrayInsnNode.desc, FontColor.desc)); append(stringBuilder, HtmlUtil.setColor(String.valueOf(multiANewArrayInsnNode.dims), FontColor.base)); break; case AbstractInsnNode.FRAME: - FrameNode frameNode = (FrameNode) instruction; + FrameNode frameNode = (FrameNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor(OpcodeUtil.FRAME.get(frameNode.type), FontColor.opcode)); append(stringBuilder, HtmlUtil.setColor(String.valueOf(frameNode.local), FontColor.desc)); append(stringBuilder, HtmlUtil.setColor(String.valueOf(frameNode.stack), FontColor.desc)); break; case AbstractInsnNode.LINE: - LineNumberNode lineNumberNode = (LineNumberNode) instruction; + LineNumberNode lineNumberNode = (LineNumberNode) getWrapper(); append(stringBuilder, HtmlUtil.setColor("LINE", FontColor.opcode)); append(stringBuilder, HtmlUtil.setColor(String.valueOf(lineNumberNode.line), FontColor.base)); append(stringBuilder, HtmlUtil.setColor("L" + OpcodeUtil.getLabelIndex(lineNumberNode.start), FontColor.base)); diff --git a/src/main/resources/lang/en_US.json b/src/main/resources/lang/en_US.json index b70ef6c..7b361b6 100644 --- a/src/main/resources/lang/en_US.json +++ b/src/main/resources/lang/en_US.json @@ -17,6 +17,7 @@ "about.java.home": "Home", "menu.file": "File", "menu.file.load": "Load...", + "menu.file.loadRecent": "Load Recent", "menu.file.save": "Save...", "menu.file.saveAllSource": "Save All Sources", "menu.config": "Config", @@ -27,6 +28,15 @@ "menu.help": "Help", "menu.help.about": "About", "menu.help.contact": "Contact", + "popup.instruction.edit": "Edit", + "popup.instruction.clone": "Clone", + "popup.instructions.remove": "Remove", + "popup.instructions.copyText": "Copy Text", + "popup.instructions.insertBefore": "Insert Before", + "popup.instructions.insertAfter": "Insert After", + "popup.instructions.moveUp": "Move Up", + "popup.instructions.moveDown": "Move Down", + "popup.expandAll": "Expand All", "class.info.name": "Name:", "class.info.sourceFile": "SourceFile:", "class.info.debugFile": "DebugFile:", @@ -44,6 +54,39 @@ "button.findNext": "Find Next", "button.findPrevious": "Find Previous", "button.save": "Save", - "dialog.wantCloseWindow": "Do you want to close", - "instruction.edit": "Edit" + "button.edit": "Edit", + "button.remove": "Remove", + "button.add": "Add", + "dialog.wantCloseWindow": "Do you want to close?", + "dialog.wantRemove": "Do you want to remove?", + "success": "Success", + "info": "Info", + "error": "Error", + "fail": "Fail", + "warning": "Warning", + "instruction.opcode": "Opcode:", + "instruction.owner": "Owner:", + "instruction.name": "Name:", + "instruction.description": "Description:", + "instruction.interface": "Interface:", + "instruction.type": "Type:", + "instruction.localOrStack": "Local/Stack:", + "instruction.local": "Local:", + "instruction.stack": "Stack:", + "instruction.varIndex": "Var Index:", + "instruction.incr": "Incr:", + "instruction.operand": "Operand:", + "instruction.bootstrapMethod": "Bootstrap Method:", + "instruction.bootstrapMethodArgument": "Bootstrap Method Argument:", + "instruction.label": "Label:", + "instruction.var": "Var:", + "instruction.handle": "Handle:", + "instruction.line": "Line:", + "instruction.start": "Start:", + "instruction.default": "Default:", + "instruction.keyOrLabel": "Keys/Labels:", + "instruction.dimension": "Dimension:", + "instruction.min": "Min:", + "instruction.max": "Max:", + "instruction.labels": "Labels:" } \ No newline at end of file diff --git a/src/main/resources/lang/zh_CN.json b/src/main/resources/lang/zh_CN.json index ad4b8a7..b1c9245 100644 --- a/src/main/resources/lang/zh_CN.json +++ b/src/main/resources/lang/zh_CN.json @@ -16,6 +16,7 @@ "about.java.home": "根目录", "menu.file": "文件", "menu.file.load": "加载...", + "menu.file.loadRecent": "最近加载", "menu.file.save": "保存...", "menu.file.saveAllSource": "保存全部源码", "menu.config": "配置", @@ -26,6 +27,15 @@ "menu.help": "帮助", "menu.help.about": "关于", "menu.help.contact": "联系", + "popup.instruction.edit": "编辑", + "popup.instruction.clone": "克隆", + "popup.instructions.remove": "移除", + "popup.instructions.copyText": "复制文本", + "popup.instructions.insertBefore": "前插入", + "popup.instructions.insertAfter": "后插入", + "popup.instructions.moveUp": "上移", + "popup.instructions.moveDown": "下移", + "popup.expandAll": "展开全部", "class.info.name": "名称:", "class.info.sourceFile": "源文件:", "class.info.debugFile": "调试文件:", @@ -43,6 +53,39 @@ "button.findNext": "查找下一个", "button.findPrevious": "查找上一个", "button.save": "保存", - "dialog.wantCloseWindow": "想要关闭吗", - "instruction.edit": "编辑" + "button.edit": "编辑", + "button.remove": "移除", + "button.add": "添加", + "dialog.wantCloseWindow": "是否要关闭?", + "dialog.wantRemove": "是否要删除?", + "success": "成功", + "info": "信息", + "error": "错误", + "fail": "失败", + "warning": "警告", + "instruction.opcode": "操作码:", + "instruction.owner": "所有者:", + "instruction.name": "名称:", + "instruction.description": "描述:", + "instruction.interface": "接口:", + "instruction.type": "类型:", + "instruction.localOrStack": "局部/堆栈:", + "instruction.local": "局部:", + "instruction.stack": "堆栈:", + "instruction.varIndex": "变量索引:", + "instruction.incr": "增量:", + "instruction.operand": "操作数:", + "instruction.bootstrapMethod": "引导方法:", + "instruction.bootstrapMethodArgument": "引导方法参数:", + "instruction.label": "标签:", + "instruction.var": "变量:", + "instruction.handle": "句柄:", + "instruction.line": "行:", + "instruction.start": "开始:", + "instruction.default": "默认:", + "instruction.keyOrLabel": "键/标签:", + "instruction.dimension": "维数:", + "instruction.min": "最小:", + "instruction.max": "最大:", + "instruction.labels": "标签:" } \ No newline at end of file