diff --git a/CHANGELOG.md b/CHANGELOG.md index 541949db0..74523da1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ### Added - SoundStreamHead has associated sprite id in its name in the tagtree - [#1485] Improved skins support, night mode +- [#1681] AS3 - context menu for adding classes on packages ## [14.4.0] - 2021-04-05 ### Added @@ -2190,6 +2191,7 @@ All notable changes to this project will be documented in this file. [alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8 [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 [#1485]: https://www.free-decompiler.com/flash/issues/1485 +[#1681]: https://www.free-decompiler.com/flash/issues/1681 [#1015]: https://www.free-decompiler.com/flash/issues/1015 [#1466]: https://www.free-decompiler.com/flash/issues/1466 [#1513]: https://www.free-decompiler.com/flash/issues/1513 diff --git a/src/com/jpexs/decompiler/flash/gui/abc/AddClassDialog.java b/src/com/jpexs/decompiler/flash/gui/abc/AddClassDialog.java new file mode 100644 index 000000000..cb8142e47 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/abc/AddClassDialog.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2021 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.abc; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.gui.AppDialog; +import com.jpexs.decompiler.flash.gui.Main; +import com.jpexs.decompiler.flash.gui.View; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +/** + * + * @author JPEXS + */ +public class AddClassDialog extends AppDialog { + + private final JButton okButton = new JButton(translate("button.ok")); + private final JButton cancelButton = new JButton(translate("button.cancel")); + + private final JTextField classNameTextField = new JTextField(30); + private String result = null; + + public AddClassDialog(Window owner) { + super(owner); + setDefaultCloseOperation(HIDE_ON_CLOSE); + setTitle(translate("dialog.title")); + + Container cnt = getContentPane(); + cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS)); + + JPanel panButtons = new JPanel(new FlowLayout()); + okButton.addActionListener(this::okButtonActionPerformed); + cancelButton.addActionListener(this::cancelButtonActionPerformed); + panButtons.add(okButton); + panButtons.add(cancelButton); + + JLabel classNameLabel = new JLabel(translate("classname")); + classNameLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + cnt.add(classNameLabel); + cnt.add(classNameTextField); + + cnt.add(panButtons); + + classNameTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + checkEnabled(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + checkEnabled(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + checkEnabled(); + } + }); + + classNameTextField.addActionListener(this::okButtonActionPerformed); + + pack(); + setModal(true); + setResizable(false); + View.setWindowIcon(this); + View.centerScreen(this); + checkEnabled(); + } + + private void checkEnabled() { + + boolean ok = true; + + if (classNameTextField.getText().isEmpty()) { + ok = false; + } + + if (classNameTextField.getText().endsWith(".")) { + ok = false; + } + + if (ok) { + SWF swf = Main.getMainFrame().getPanel().getCurrentSwf(); + List classNames = new ArrayList<>(); + classNames.add(classNameTextField.getText()); + try { + List scriptPacks = swf.getScriptPacksByClassNames(classNames); + if (!scriptPacks.isEmpty()) { + ok = false; + } + } catch (Exception ex) { + ok = false; + } + } + + okButton.setEnabled(ok); + } + + private void okButtonActionPerformed(ActionEvent evt) { + if (!okButton.isEnabled()) { + return; + } + result = classNameTextField.getText(); + setVisible(false); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + result = null; + setVisible(false); + } + + public String showDialog() { + return showDialog(""); + } + public String showDialog(String pkg) { + classNameTextField.setText(pkg); + result = null; + setVisible(true); + return result; + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog.properties new file mode 100644 index 000000000..0b8a039d1 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog.properties @@ -0,0 +1,20 @@ +# Copyright (C) 2021 JPEXS +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +dialog.title = Add script +button.ok = OK +button.cancel = Cancel + +classname = Fully qualified class name: \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_cs.properties new file mode 100644 index 000000000..f85ee5568 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_cs.properties @@ -0,0 +1,20 @@ +# Copyright (C) 2021 JPEXS +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +dialog.title = P\u0159idat skript +button.ok = OK +button.cancel = Storno + +classname = Pln\u011b kvalifikovan\u00fd n\u00e1zev t\u0159\u00eddy: diff --git a/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_ja.properties b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_ja.properties new file mode 100644 index 000000000..a18c76962 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_ja.properties @@ -0,0 +1,20 @@ +# Copyright (C) 2021 JPEXS +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +dialog.title = \u30b9\u30af\u30ea\u30d7\u30c8\u3092\u8ffd\u52a0 +button.ok = OK +button.cancel = \u30ad\u30e3\u30f3\u30bb\u30eb + +classname = \u5b8c\u5168\u4fee\u98fe\u30af\u30e9\u30b9\u540d (\u30d1\u30c3\u30b1\u30fc\u30b8\u3082\u542b\u3081\u305f\u30af\u30e9\u30b9\u540d): \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_zh.properties b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_zh.properties new file mode 100644 index 000000000..2da649b96 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/locales/abc/AddClassDialog_zh.properties @@ -0,0 +1,4 @@ +dialog.title = \u6dfb\u52a0\u811a\u672c +button.ok = \u786e\u5b9a +button.cancel = \u53d6\u6d88 +classname = \u5168\u9650\u5b9a\u7c7b\u540d diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 99f5402c5..3a2807b95 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.gui.MainPanel; import com.jpexs.decompiler.flash.gui.ReplaceCharacterDialog; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.gui.ViewMessages; +import com.jpexs.decompiler.flash.gui.abc.AddClassDialog; import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel; import com.jpexs.decompiler.flash.gui.action.AddScriptDialog; import com.jpexs.decompiler.flash.tags.ABCContainerTag; @@ -498,6 +499,9 @@ public class TagTreeContextMenu extends JPopupMenu { if (firstItem instanceof ClassesListTreeModel) { addAs3ClassMenuItem.setVisible(true); } + if (firstItem instanceof AS3Package) { + addAs3ClassMenuItem.setVisible(true); + } if (firstItem instanceof CharacterTag) { replaceWithTagMenuItem.setVisible(true); @@ -840,29 +844,37 @@ public class TagTreeContextMenu extends JPopupMenu { private void addAs3ClassActionPerformed(ActionEvent evt) { List sel = tagTree.getSelected(); if (!sel.isEmpty()) { + SWF swf = null; + String preselected = ""; if (sel.get(0) instanceof ClassesListTreeModel) { ClassesListTreeModel cl = (ClassesListTreeModel) sel.get(0); - SWF swf = cl.getSwf(); - String className = ""; - String parts[]; - loopinput: - while (true) { - className = ViewMessages.showInputDialog(mainPanel, AppDialog.translateForDialog("classname", AddScriptDialog.class), className); - if (className == null || className.isEmpty()) { - return; + swf = cl.getSwf(); + } + if (sel.get(0) instanceof AS3Package) { + AS3Package pkg = (AS3Package) sel.get(0); + swf = pkg.getSwf(); + TreePath tp = tagTree.getSelectionPaths()[0]; + Object[] path = tp.getPath(); + for (int p = path.length - 1; p >= 0; p--) { + if (path[p] instanceof ClassesListTreeModel) { + break; } - - - parts = className.contains(".") ? className.split("\\.") : new String[]{className}; - DottedChain classNameDc = new DottedChain(parts, ""); - for (ABCContainerTag ct : swf.getAbcList()) { - if (ct.getABC().findClassByName(classNameDc) > -1) { - ViewMessages.showMessageDialog(mainPanel, AppDialog.translateForDialog("message.classexists", AddScriptDialog.class), mainPanel.translate("error"), JOptionPane.ERROR_MESSAGE); - continue loopinput; - } - } - break; + preselected = ((AS3Package) path[p]).packageName + "." + preselected; } + } + + TreePath scriptsPath = tagTree.getSelectionPaths()[0]; + while (!(scriptsPath.getLastPathComponent() instanceof ClassesListTreeModel)) { + scriptsPath = scriptsPath.getParentPath(); + } + + { + AddClassDialog acd = new AddClassDialog(Main.getDefaultDialogsOwner()); + String className = acd.showDialog(preselected); + if (className == null) { + return; + } + String[] parts = className.contains(".") ? className.split("\\.") : new String[]{className}; DoABC2Tag doAbc = new DoABC2Tag(swf); doAbc.setTimelined(swf); @@ -917,9 +929,6 @@ public class TagTreeContextMenu extends JPopupMenu { Object item = mainPanel.tagTree.getModel().getScriptsNode(swf); - TreePath selection = mainPanel.tagTree.getSelectionPath(); - TreePath swfPath = selection.getParentPath(); - TreePath scriptsPath = swfPath.pathByAddingChild(item); TreePath classPath = scriptsPath; for (int i = 0; i < parts.length; i++) {