mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 01:41:17 +00:00
TagTree context menu moved to separate control, support to loadmultiple inner swfs from binary data tags
This commit is contained in:
@@ -130,7 +130,7 @@ public class FolderPreviewPanel extends JPanel {
|
||||
}
|
||||
|
||||
if (e.getButton() == MouseEvent.BUTTON3) {
|
||||
mainPanel.tagTree.updateContextMenu(mainPanel.tagTree.swfs, new ArrayList<>(selectedItems.values()));
|
||||
mainPanel.tagTree.contextPopupMenu.update(new ArrayList<>(selectedItems.values()));
|
||||
mainPanel.tagTree.contextPopupMenu.show(FolderPreviewPanel.this, e.getX(), e.getY());
|
||||
}
|
||||
repaint();
|
||||
|
||||
@@ -471,7 +471,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
|
||||
}
|
||||
});
|
||||
|
||||
tagTree.createContextMenu(swfs);
|
||||
tagTree.createContextMenu();
|
||||
|
||||
dumpTree = new DumpTree(null, this);
|
||||
dumpTree.addTreeSelectionListener(this);
|
||||
@@ -1120,6 +1120,10 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
|
||||
}
|
||||
}
|
||||
|
||||
public List<SWFList> getSwfs() {
|
||||
return swfs;
|
||||
}
|
||||
|
||||
public SWFList getCurrentSwfList() {
|
||||
SWF swf = getCurrentSwf();
|
||||
if (swf == null) {
|
||||
@@ -1140,7 +1144,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
|
||||
return swfs.get(0).get(0);
|
||||
}
|
||||
|
||||
if (treeNode instanceof SWFBundle) {
|
||||
if (treeNode instanceof SWFList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ import com.jpexs.decompiler.flash.SWC;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.ZippedSWFBundle;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.gui.Main;
|
||||
import com.jpexs.decompiler.flash.gui.MainFrameRibbonMenu;
|
||||
import com.jpexs.decompiler.flash.gui.MainPanel;
|
||||
import com.jpexs.decompiler.flash.gui.TreeNodeType;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
@@ -96,8 +94,6 @@ import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
|
||||
@@ -109,42 +105,26 @@ import com.jpexs.decompiler.flash.timeline.AS3Package;
|
||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||
import com.jpexs.decompiler.flash.timeline.FrameScript;
|
||||
import com.jpexs.decompiler.flash.timeline.TagScript;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.FolderItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.HeaderItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.SWFList;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.basic.BasicLabelUI;
|
||||
import javax.swing.plaf.basic.BasicTreeUI;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
|
||||
@@ -152,16 +132,9 @@ import javax.swing.tree.TreeSelectionModel;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TagTree extends JTree implements ActionListener {
|
||||
|
||||
private static final String ACTION_RAW_EDIT = "RAWEDIT";
|
||||
private static final String ACTION_JUMP_TO_CHARACTER = "JUMPTOCHARACTER";
|
||||
private static final String ACTION_REMOVE_ITEM = "REMOVEITEM";
|
||||
private static final String ACTION_REMOVE_ITEM_WITH_DEPENDENCIES = "REMOVEITEMWITHDEPENDENCIES";
|
||||
private static final String ACTION_CLOSE_SWF = "CLOSESWF";
|
||||
private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE";
|
||||
private static final String ACTION_OPEN_SWFINSIDE = "OPENSWFINSIDE";
|
||||
public class TagTree extends JTree {
|
||||
|
||||
public TagTreeContextMenu contextPopupMenu;
|
||||
private final MainPanel mainPanel;
|
||||
|
||||
public class TagTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
@@ -252,6 +225,10 @@ public class TagTree extends JTree implements ActionListener {
|
||||
});
|
||||
}
|
||||
|
||||
public void createContextMenu() {
|
||||
contextPopupMenu = new TagTreeContextMenu(this, mainPanel);
|
||||
}
|
||||
|
||||
public static TreeNodeType getTreeNodeType(TreeItem t) {
|
||||
|
||||
if (t instanceof TagScript) {
|
||||
@@ -425,313 +402,6 @@ public class TagTree extends JTree implements ActionListener {
|
||||
SoundStreamBlockTag.ID, SoundStreamHeadTag.ID, SoundStreamHead2Tag.ID);
|
||||
}
|
||||
|
||||
JMenuItem expandRecursiveMenuItem;
|
||||
JMenuItem removeMenuItem;
|
||||
JMenuItem removeWithDependenciesMenuItem;
|
||||
JMenuItem exportSelectionMenuItem;
|
||||
JMenuItem replaceSelectionMenuItem;
|
||||
JMenuItem rawEditMenuItem;
|
||||
JMenuItem jumpToCharacterMenuItem;
|
||||
JMenuItem closeSelectionMenuItem;
|
||||
JMenu addTagMenu;
|
||||
JMenu moveTagMenu;
|
||||
JMenuItem openSWFInsideTagMenuItem;
|
||||
public JPopupMenu contextPopupMenu;
|
||||
public List<SWFList> swfs;
|
||||
|
||||
public void createContextMenu(final List<SWFList> swfs) {
|
||||
this.swfs = swfs;
|
||||
contextPopupMenu = new JPopupMenu();
|
||||
expandRecursiveMenuItem = new JMenuItem(mainPanel.translate("contextmenu.expandAll"));
|
||||
expandRecursiveMenuItem.addActionListener(this);
|
||||
expandRecursiveMenuItem.setActionCommand(ACTION_EXPAND_RECURSIVE);
|
||||
contextPopupMenu.add(expandRecursiveMenuItem);
|
||||
|
||||
removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove"));
|
||||
removeMenuItem.addActionListener(this);
|
||||
removeMenuItem.setActionCommand(ACTION_REMOVE_ITEM);
|
||||
contextPopupMenu.add(removeMenuItem);
|
||||
|
||||
removeWithDependenciesMenuItem = new JMenuItem(mainPanel.translate("contextmenu.removeWithDependencies"));
|
||||
removeWithDependenciesMenuItem.addActionListener(this);
|
||||
removeWithDependenciesMenuItem.setActionCommand(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
|
||||
contextPopupMenu.add(removeWithDependenciesMenuItem);
|
||||
|
||||
exportSelectionMenuItem = new JMenuItem(mainPanel.translate("menu.file.export.selection"));
|
||||
exportSelectionMenuItem.setActionCommand(MainFrameRibbonMenu.ACTION_EXPORT_SEL);
|
||||
exportSelectionMenuItem.addActionListener(mainPanel);
|
||||
contextPopupMenu.add(exportSelectionMenuItem);
|
||||
|
||||
replaceSelectionMenuItem = new JMenuItem(mainPanel.translate("button.replace"));
|
||||
replaceSelectionMenuItem.setActionCommand(MainPanel.ACTION_REPLACE);
|
||||
replaceSelectionMenuItem.addActionListener(mainPanel);
|
||||
contextPopupMenu.add(replaceSelectionMenuItem);
|
||||
|
||||
rawEditMenuItem = new JMenuItem(mainPanel.translate("contextmenu.rawEdit"));
|
||||
rawEditMenuItem.setActionCommand(ACTION_RAW_EDIT);
|
||||
rawEditMenuItem.addActionListener(this);
|
||||
rawEditMenuItem.setVisible(false);
|
||||
contextPopupMenu.add(rawEditMenuItem);
|
||||
|
||||
jumpToCharacterMenuItem = new JMenuItem(mainPanel.translate("contextmenu.jumpToCharacter"));
|
||||
jumpToCharacterMenuItem.setActionCommand(ACTION_JUMP_TO_CHARACTER);
|
||||
jumpToCharacterMenuItem.addActionListener(this);
|
||||
jumpToCharacterMenuItem.setVisible(false);
|
||||
contextPopupMenu.add(jumpToCharacterMenuItem);
|
||||
|
||||
closeSelectionMenuItem = new JMenuItem(mainPanel.translate("contextmenu.closeSwf"));
|
||||
closeSelectionMenuItem.setActionCommand(ACTION_CLOSE_SWF);
|
||||
closeSelectionMenuItem.addActionListener(this);
|
||||
contextPopupMenu.add(closeSelectionMenuItem);
|
||||
|
||||
addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag"));
|
||||
contextPopupMenu.add(addTagMenu);
|
||||
|
||||
moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag"));
|
||||
contextPopupMenu.add(moveTagMenu);
|
||||
|
||||
openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside"));
|
||||
contextPopupMenu.add(openSWFInsideTagMenuItem);
|
||||
openSWFInsideTagMenuItem.setActionCommand(ACTION_OPEN_SWFINSIDE);
|
||||
openSWFInsideTagMenuItem.addActionListener(this);
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
|
||||
int row = getClosestRowForLocation(e.getX(), e.getY());
|
||||
int[] selectionRows = getSelectionRows();
|
||||
if (!Helper.contains(selectionRows, row)) {
|
||||
setSelectionRow(row);
|
||||
}
|
||||
|
||||
TreePath[] paths = getSelectionPaths();
|
||||
if (paths == null || paths.length == 0) {
|
||||
return;
|
||||
}
|
||||
boolean allSelectedIsTagOrFrame = true;
|
||||
for (TreePath treePath : paths) {
|
||||
TreeItem tag = (TreeItem) treePath.getLastPathComponent();
|
||||
if (!(tag instanceof Tag) && !(tag instanceof Frame)) {
|
||||
allSelectedIsTagOrFrame = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
replaceSelectionMenuItem.setVisible(false);
|
||||
closeSelectionMenuItem.setVisible(false);
|
||||
moveTagMenu.setVisible(false);
|
||||
addTagMenu.setVisible(false);
|
||||
expandRecursiveMenuItem.setVisible(false);
|
||||
openSWFInsideTagMenuItem.setVisible(false);
|
||||
|
||||
if (paths.length == 1) {
|
||||
TreeItem item = (TreeItem) paths[0].getLastPathComponent();
|
||||
List<TreeItem> li = new ArrayList<>();
|
||||
li.add(item);
|
||||
updateContextMenu(swfs, li);
|
||||
}
|
||||
|
||||
removeMenuItem.setVisible(allSelectedIsTagOrFrame);
|
||||
exportSelectionMenuItem.setEnabled(hasExportableNodes());
|
||||
contextPopupMenu.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateContextMenu(final List<SWFList> swfs, List<TreeItem> items) {
|
||||
|
||||
replaceSelectionMenuItem.setVisible(false);
|
||||
closeSelectionMenuItem.setVisible(false);
|
||||
moveTagMenu.setVisible(false);
|
||||
addTagMenu.setVisible(false);
|
||||
expandRecursiveMenuItem.setVisible(false);
|
||||
openSWFInsideTagMenuItem.setVisible(false);
|
||||
removeMenuItem.setVisible(true);
|
||||
for (TreeItem t : items) {
|
||||
if (!((t instanceof Tag) || (t instanceof Frame))) {
|
||||
removeMenuItem.setVisible(false);
|
||||
}
|
||||
}
|
||||
exportSelectionMenuItem.setEnabled(!items.isEmpty() && !getSelection(items.get(0).getSwf(), items).isEmpty());
|
||||
|
||||
final TreeItem item = items.get(0);
|
||||
if (item instanceof ImageTag && ((ImageTag) item).importSupported()) {
|
||||
replaceSelectionMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (item instanceof DefineBinaryDataTag) {
|
||||
replaceSelectionMenuItem.setVisible(true);
|
||||
DefineBinaryDataTag bin = (DefineBinaryDataTag) item;
|
||||
if (bin.isSwfData()) {
|
||||
openSWFInsideTagMenuItem.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (item instanceof DefineSoundTag) {
|
||||
replaceSelectionMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (item instanceof SWF) {
|
||||
closeSelectionMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
List<Integer> allowedTagTypes = null;
|
||||
if (item instanceof FolderItem) {
|
||||
allowedTagTypes = getSwfFolderItemNestedTagIds(((FolderItem) item).getName(), item.getSwf().gfx);
|
||||
} else if (item instanceof DefineSpriteTag) {
|
||||
allowedTagTypes = getSpriteNestedTagIds();
|
||||
}
|
||||
|
||||
addTagMenu.removeAll();
|
||||
if (allowedTagTypes != null) {
|
||||
for (Integer tagId : allowedTagTypes) {
|
||||
final Class cl = TagIdClassMap.getClassByTagId(tagId);
|
||||
JMenuItem tagItem = new JMenuItem(cl.getSimpleName());
|
||||
tagItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
try {
|
||||
SWF swf = item.getSwf();
|
||||
Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf});
|
||||
boolean isDefineSprite = item instanceof DefineSpriteTag;
|
||||
Timelined timelined = isDefineSprite ? (DefineSpriteTag) item : swf;
|
||||
t.setTimelined(timelined);
|
||||
if (isDefineSprite) {
|
||||
((DefineSpriteTag) item).subTags.add(t);
|
||||
} else {
|
||||
swf.tags.add(t);
|
||||
}
|
||||
timelined.getTimeline().reset();
|
||||
swf.updateCharacters();
|
||||
mainPanel.refreshTree();
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
Logger.getLogger(TagTree.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
addTagMenu.add(tagItem);
|
||||
}
|
||||
addTagMenu.setVisible(true);
|
||||
}
|
||||
|
||||
if (item instanceof Tag && swfs.size() > 1) {
|
||||
final Tag tag = (Tag) item;
|
||||
moveTagMenu.removeAll();
|
||||
for (SWFList targetSwfList : swfs) {
|
||||
for (final SWF targetSwf : targetSwfList) {
|
||||
if (targetSwf != tag.getSwf()) {
|
||||
JMenuItem swfItem = new JMenuItem(targetSwf.getShortFileName());
|
||||
swfItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
tag.getSwf().tags.remove(tag);
|
||||
tag.setSwf(targetSwf);
|
||||
targetSwf.tags.add(tag);
|
||||
mainPanel.refreshTree();
|
||||
}
|
||||
});
|
||||
moveTagMenu.add(swfItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
moveTagMenu.setVisible(true);
|
||||
}
|
||||
|
||||
TreeModel model = getModel();
|
||||
expandRecursiveMenuItem.setVisible(model.getChildCount(item) > 0);
|
||||
|
||||
jumpToCharacterMenuItem.setVisible(item instanceof CharacterIdTag && !(item instanceof CharacterTag));
|
||||
|
||||
rawEditMenuItem.setVisible(item instanceof Tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (e.getActionCommand()) {
|
||||
case ACTION_OPEN_SWFINSIDE:
|
||||
Object itemo = getLastSelectedPathComponent();
|
||||
if (itemo == null) {
|
||||
return;
|
||||
}
|
||||
if (itemo instanceof DefineBinaryDataTag) {
|
||||
mainPanel.loadFromBinaryTag((DefineBinaryDataTag) itemo);
|
||||
}
|
||||
break;
|
||||
case ACTION_RAW_EDIT: {
|
||||
TreeItem itemr = getCurrentTreeItem();
|
||||
if (itemr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mainPanel.showGenericTag((Tag) itemr);
|
||||
}
|
||||
break;
|
||||
case ACTION_JUMP_TO_CHARACTER: {
|
||||
TreeItem itemj = getCurrentTreeItem();
|
||||
if (itemj == null || !(itemj instanceof CharacterIdTag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterIdTag characterIdTag = (CharacterIdTag) itemj;
|
||||
mainPanel.setTagTreeSelectedNode(itemj.getSwf().characters.get(characterIdTag.getCharacterId()));
|
||||
}
|
||||
break;
|
||||
case ACTION_EXPAND_RECURSIVE: {
|
||||
TreePath path = getSelectionPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
View.expandTreeNodesRecursive(this, path, true);
|
||||
}
|
||||
break;
|
||||
case ACTION_REMOVE_ITEM:
|
||||
case ACTION_REMOVE_ITEM_WITH_DEPENDENCIES:
|
||||
List<TreeItem> sel = getSelected(this);
|
||||
|
||||
List<Tag> tagsToRemove = new ArrayList<>();
|
||||
for (TreeItem tag : sel) {
|
||||
if (tag instanceof Tag) {
|
||||
tagsToRemove.add((Tag) tag);
|
||||
} else if (tag instanceof Frame) {
|
||||
Frame frameNode = (Frame) tag;
|
||||
Frame frame = frameNode.timeline.getFrames().get(frameNode.frame);
|
||||
if (frame.showFrameTag != null) {
|
||||
tagsToRemove.add(frame.showFrameTag);
|
||||
} else {
|
||||
// this should be the last frame, so remove the inner tags
|
||||
tagsToRemove.addAll(frame.innerTags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean removeDependencies = e.getActionCommand().equals(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
|
||||
if (tagsToRemove.size() == 1) {
|
||||
Tag tag = tagsToRemove.get(0);
|
||||
if (View.showConfirmDialog(this, mainPanel.translate("message.confirm.remove").replace("%item%", tag.toString()), mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
|
||||
tag.getSwf().removeTag(tag, removeDependencies);
|
||||
mainPanel.refreshTree();
|
||||
}
|
||||
} else if (tagsToRemove.size() > 1) {
|
||||
if (View.showConfirmDialog(this, mainPanel.translate("message.confirm.removemultiple").replace("%count%", Integer.toString(tagsToRemove.size())), mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
|
||||
for (Tag tag : tagsToRemove) {
|
||||
tag.getSwf().removeTag(tag, removeDependencies);
|
||||
}
|
||||
mainPanel.refreshTree();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_CLOSE_SWF: {
|
||||
Main.closeFile(mainPanel.getCurrentSwfList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasExportableNodes() {
|
||||
return !getSelection(mainPanel.getCurrentSwf()).isEmpty();
|
||||
}
|
||||
@@ -794,6 +464,9 @@ public class TagTree extends JTree implements ActionListener {
|
||||
public List<TreeItem> getSelection(SWF swf, List<TreeItem> sel) {
|
||||
List<TreeItem> ret = new ArrayList<>();
|
||||
for (TreeItem d : sel) {
|
||||
if (d instanceof SWFList) {
|
||||
continue;
|
||||
}
|
||||
if (d.getSwf() != swf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui.tagtree;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.gui.Main;
|
||||
import com.jpexs.decompiler.flash.gui.MainFrameRibbonMenu;
|
||||
import com.jpexs.decompiler.flash.gui.MainPanel;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.decompiler.flash.treeitems.FolderItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.SWFList;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TagTreeContextMenu extends JPopupMenu implements ActionListener {
|
||||
|
||||
private static final String ACTION_RAW_EDIT = "RAWEDIT";
|
||||
private static final String ACTION_JUMP_TO_CHARACTER = "JUMPTOCHARACTER";
|
||||
private static final String ACTION_REMOVE_ITEM = "REMOVEITEM";
|
||||
private static final String ACTION_REMOVE_ITEM_WITH_DEPENDENCIES = "REMOVEITEMWITHDEPENDENCIES";
|
||||
private static final String ACTION_CLOSE_SWF = "CLOSESWF";
|
||||
private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE";
|
||||
private static final String ACTION_OPEN_SWFINSIDE = "OPENSWFINSIDE";
|
||||
|
||||
private final MainPanel mainPanel;
|
||||
private final TagTree tagTree;
|
||||
|
||||
private JMenuItem expandRecursiveMenuItem;
|
||||
private JMenuItem removeMenuItem;
|
||||
private JMenuItem removeWithDependenciesMenuItem;
|
||||
private JMenuItem exportSelectionMenuItem;
|
||||
private JMenuItem replaceMenuItem;
|
||||
private JMenuItem rawEditMenuItem;
|
||||
private JMenuItem jumpToCharacterMenuItem;
|
||||
private JMenuItem closeMenuItem;
|
||||
private JMenu addTagMenu;
|
||||
private JMenu moveTagMenu;
|
||||
private JMenuItem openSWFInsideTagMenuItem;
|
||||
|
||||
public TagTreeContextMenu(final TagTree tagTree, MainPanel mainPanel) {
|
||||
this.mainPanel = mainPanel;
|
||||
this.tagTree = tagTree;
|
||||
expandRecursiveMenuItem = new JMenuItem(mainPanel.translate("contextmenu.expandAll"));
|
||||
expandRecursiveMenuItem.addActionListener(this);
|
||||
expandRecursiveMenuItem.setActionCommand(ACTION_EXPAND_RECURSIVE);
|
||||
add(expandRecursiveMenuItem);
|
||||
|
||||
removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove"));
|
||||
removeMenuItem.addActionListener(this);
|
||||
removeMenuItem.setActionCommand(ACTION_REMOVE_ITEM);
|
||||
add(removeMenuItem);
|
||||
|
||||
removeWithDependenciesMenuItem = new JMenuItem(mainPanel.translate("contextmenu.removeWithDependencies"));
|
||||
removeWithDependenciesMenuItem.addActionListener(this);
|
||||
removeWithDependenciesMenuItem.setActionCommand(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
|
||||
add(removeWithDependenciesMenuItem);
|
||||
|
||||
exportSelectionMenuItem = new JMenuItem(mainPanel.translate("menu.file.export.selection"));
|
||||
exportSelectionMenuItem.setActionCommand(MainFrameRibbonMenu.ACTION_EXPORT_SEL);
|
||||
exportSelectionMenuItem.addActionListener(mainPanel);
|
||||
add(exportSelectionMenuItem);
|
||||
|
||||
replaceMenuItem = new JMenuItem(mainPanel.translate("button.replace"));
|
||||
replaceMenuItem.setActionCommand(MainPanel.ACTION_REPLACE);
|
||||
replaceMenuItem.addActionListener(mainPanel);
|
||||
add(replaceMenuItem);
|
||||
|
||||
rawEditMenuItem = new JMenuItem(mainPanel.translate("contextmenu.rawEdit"));
|
||||
rawEditMenuItem.setActionCommand(ACTION_RAW_EDIT);
|
||||
rawEditMenuItem.addActionListener(this);
|
||||
rawEditMenuItem.setVisible(false);
|
||||
add(rawEditMenuItem);
|
||||
|
||||
jumpToCharacterMenuItem = new JMenuItem(mainPanel.translate("contextmenu.jumpToCharacter"));
|
||||
jumpToCharacterMenuItem.setActionCommand(ACTION_JUMP_TO_CHARACTER);
|
||||
jumpToCharacterMenuItem.addActionListener(this);
|
||||
jumpToCharacterMenuItem.setVisible(false);
|
||||
add(jumpToCharacterMenuItem);
|
||||
|
||||
closeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.closeSwf"));
|
||||
closeMenuItem.setActionCommand(ACTION_CLOSE_SWF);
|
||||
closeMenuItem.addActionListener(this);
|
||||
add(closeMenuItem);
|
||||
|
||||
addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag"));
|
||||
add(addTagMenu);
|
||||
|
||||
moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag"));
|
||||
add(moveTagMenu);
|
||||
|
||||
openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside"));
|
||||
add(openSWFInsideTagMenuItem);
|
||||
openSWFInsideTagMenuItem.setActionCommand(ACTION_OPEN_SWFINSIDE);
|
||||
openSWFInsideTagMenuItem.addActionListener(this);
|
||||
|
||||
tagTree.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
|
||||
int row = tagTree.getClosestRowForLocation(e.getX(), e.getY());
|
||||
int[] selectionRows = tagTree.getSelectionRows();
|
||||
if (!Helper.contains(selectionRows, row)) {
|
||||
tagTree.setSelectionRow(row);
|
||||
}
|
||||
|
||||
TreePath[] paths = tagTree.getSelectionPaths();
|
||||
if (paths == null || paths.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<TreeItem> li = new ArrayList<>();
|
||||
for (TreePath treePath : paths) {
|
||||
TreeItem item = (TreeItem) treePath.getLastPathComponent();
|
||||
li.add(item);
|
||||
}
|
||||
|
||||
update(li);
|
||||
show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void update(List<TreeItem> items) {
|
||||
|
||||
if (items.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<SWFList> swfs = mainPanel.getSwfs();
|
||||
|
||||
boolean allSelectedIsTagOrFrame = true;
|
||||
for (TreeItem item : items) {
|
||||
if (!(item instanceof Tag) && !(item instanceof Frame)) {
|
||||
allSelectedIsTagOrFrame = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean allSelectedIsBinaryData = true;
|
||||
for (TreeItem item : items) {
|
||||
if (!(item instanceof DefineBinaryDataTag)) {
|
||||
allSelectedIsBinaryData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean allSelectedIsSwf = true;
|
||||
for (TreeItem item : items) {
|
||||
if (!(item instanceof SWF) && !(item instanceof SWFList)) {
|
||||
allSelectedIsSwf = false;
|
||||
break;
|
||||
} else if (item instanceof SWF) {
|
||||
// Do not allow to close SWF in bundle
|
||||
if (((SWF) item).swfList.isBundle) {
|
||||
allSelectedIsSwf = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expandRecursiveMenuItem.setVisible(false);
|
||||
removeMenuItem.setVisible(allSelectedIsTagOrFrame);
|
||||
removeWithDependenciesMenuItem.setVisible(allSelectedIsTagOrFrame);
|
||||
exportSelectionMenuItem.setEnabled(tagTree.hasExportableNodes());
|
||||
replaceMenuItem.setVisible(false);
|
||||
rawEditMenuItem.setVisible(false);
|
||||
jumpToCharacterMenuItem.setVisible(false);
|
||||
closeMenuItem.setVisible(allSelectedIsSwf);
|
||||
addTagMenu.setVisible(false);
|
||||
moveTagMenu.setVisible(false);
|
||||
openSWFInsideTagMenuItem.setVisible(false);
|
||||
|
||||
final TreeItem firstItem = items.get(0);
|
||||
boolean singleSelect = items.size() == 1;
|
||||
|
||||
if (singleSelect) {
|
||||
// replace
|
||||
if (firstItem instanceof ImageTag && ((ImageTag) firstItem).importSupported()) {
|
||||
replaceMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (firstItem instanceof DefineBinaryDataTag) {
|
||||
replaceMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (firstItem instanceof DefineSoundTag) {
|
||||
replaceMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
List<Integer> allowedTagTypes = null;
|
||||
if (firstItem instanceof FolderItem) {
|
||||
allowedTagTypes = tagTree.getSwfFolderItemNestedTagIds(((FolderItem) firstItem).getName(), firstItem.getSwf().gfx);
|
||||
} else if (firstItem instanceof DefineSpriteTag) {
|
||||
allowedTagTypes = tagTree.getSpriteNestedTagIds();
|
||||
}
|
||||
|
||||
addTagMenu.removeAll();
|
||||
if (allowedTagTypes != null) {
|
||||
for (Integer tagId : allowedTagTypes) {
|
||||
final Class cl = TagIdClassMap.getClassByTagId(tagId);
|
||||
JMenuItem tagItem = new JMenuItem(cl.getSimpleName());
|
||||
tagItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
try {
|
||||
SWF swf = firstItem.getSwf();
|
||||
Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf});
|
||||
boolean isDefineSprite = firstItem instanceof DefineSpriteTag;
|
||||
Timelined timelined = isDefineSprite ? (DefineSpriteTag) firstItem : swf;
|
||||
t.setTimelined(timelined);
|
||||
if (isDefineSprite) {
|
||||
((DefineSpriteTag) firstItem).subTags.add(t);
|
||||
} else {
|
||||
swf.tags.add(t);
|
||||
}
|
||||
timelined.getTimeline().reset();
|
||||
swf.updateCharacters();
|
||||
mainPanel.refreshTree();
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
Logger.getLogger(TagTree.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
addTagMenu.add(tagItem);
|
||||
}
|
||||
addTagMenu.setVisible(true);
|
||||
}
|
||||
|
||||
if (firstItem instanceof Tag && swfs.size() > 1) {
|
||||
final Tag tag = (Tag) firstItem;
|
||||
moveTagMenu.removeAll();
|
||||
for (SWFList targetSwfList : swfs) {
|
||||
for (final SWF targetSwf : targetSwfList) {
|
||||
if (targetSwf != tag.getSwf()) {
|
||||
JMenuItem swfItem = new JMenuItem(targetSwf.getShortFileName());
|
||||
swfItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
tag.getSwf().tags.remove(tag);
|
||||
tag.setSwf(targetSwf);
|
||||
targetSwf.tags.add(tag);
|
||||
mainPanel.refreshTree();
|
||||
}
|
||||
});
|
||||
moveTagMenu.add(swfItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
moveTagMenu.setVisible(true);
|
||||
}
|
||||
|
||||
if (tagTree.getModel().getChildCount(firstItem) > 0) {
|
||||
expandRecursiveMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (firstItem instanceof CharacterIdTag && !(firstItem instanceof CharacterTag)) {
|
||||
jumpToCharacterMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (firstItem instanceof Tag) {
|
||||
rawEditMenuItem.setVisible(firstItem instanceof Tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (allSelectedIsBinaryData) {
|
||||
boolean anyInnerSwf = false;
|
||||
for (TreeItem item : items) {
|
||||
DefineBinaryDataTag binary = (DefineBinaryDataTag) item;
|
||||
|
||||
// inner swf is not loaded yet
|
||||
if (binary.innerSwf == null && binary.isSwfData()) {
|
||||
anyInnerSwf = true;
|
||||
}
|
||||
}
|
||||
|
||||
openSWFInsideTagMenuItem.setVisible(anyInnerSwf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (e.getActionCommand()) {
|
||||
case ACTION_OPEN_SWFINSIDE: {
|
||||
List<TreeItem> sel = tagTree.getSelected(tagTree);
|
||||
for (TreeItem item : sel) {
|
||||
if (item instanceof DefineBinaryDataTag) {
|
||||
mainPanel.loadFromBinaryTag((DefineBinaryDataTag) item);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_RAW_EDIT: {
|
||||
TreeItem itemr = tagTree.getCurrentTreeItem();
|
||||
if (itemr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mainPanel.showGenericTag((Tag) itemr);
|
||||
}
|
||||
break;
|
||||
case ACTION_JUMP_TO_CHARACTER: {
|
||||
TreeItem itemj = tagTree.getCurrentTreeItem();
|
||||
if (itemj == null || !(itemj instanceof CharacterIdTag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterIdTag characterIdTag = (CharacterIdTag) itemj;
|
||||
mainPanel.setTagTreeSelectedNode(itemj.getSwf().characters.get(characterIdTag.getCharacterId()));
|
||||
}
|
||||
break;
|
||||
case ACTION_EXPAND_RECURSIVE: {
|
||||
TreePath path = tagTree.getSelectionPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
View.expandTreeNodesRecursive(tagTree, path, true);
|
||||
}
|
||||
break;
|
||||
case ACTION_REMOVE_ITEM:
|
||||
case ACTION_REMOVE_ITEM_WITH_DEPENDENCIES: {
|
||||
List<TreeItem> sel = tagTree.getSelected(tagTree);
|
||||
|
||||
List<Tag> tagsToRemove = new ArrayList<>();
|
||||
for (TreeItem tag : sel) {
|
||||
if (tag instanceof Tag) {
|
||||
tagsToRemove.add((Tag) tag);
|
||||
} else if (tag instanceof Frame) {
|
||||
Frame frameNode = (Frame) tag;
|
||||
Frame frame = frameNode.timeline.getFrames().get(frameNode.frame);
|
||||
if (frame.showFrameTag != null) {
|
||||
tagsToRemove.add(frame.showFrameTag);
|
||||
} else {
|
||||
// this should be the last frame, so remove the inner tags
|
||||
tagsToRemove.addAll(frame.innerTags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean removeDependencies = e.getActionCommand().equals(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
|
||||
if (tagsToRemove.size() == 1) {
|
||||
Tag tag = tagsToRemove.get(0);
|
||||
if (View.showConfirmDialog(this, mainPanel.translate("message.confirm.remove").replace("%item%", tag.toString()), mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
|
||||
tag.getSwf().removeTag(tag, removeDependencies);
|
||||
mainPanel.refreshTree();
|
||||
}
|
||||
} else if (tagsToRemove.size() > 1) {
|
||||
if (View.showConfirmDialog(this, mainPanel.translate("message.confirm.removemultiple").replace("%count%", Integer.toString(tagsToRemove.size())), mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
|
||||
for (Tag tag : tagsToRemove) {
|
||||
tag.getSwf().removeTag(tag, removeDependencies);
|
||||
}
|
||||
mainPanel.refreshTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_CLOSE_SWF: {
|
||||
List<TreeItem> sel = tagTree.getSelected(tagTree);
|
||||
for (TreeItem item : sel) {
|
||||
if (item instanceof SWF) {
|
||||
Main.closeFile(((SWF) item).swfList);
|
||||
} else if (item instanceof SWFList) {
|
||||
Main.closeFile((SWFList) item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user