/*
* Copyright (C) 2010-2016 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.AppDialog;
import com.jpexs.decompiler.flash.gui.Main;
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.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
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.tags.base.ShapeTag;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.TagScript;
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.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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 {
private static final Logger logger = Logger.getLogger(TagTreeContextMenu.class.getName());
private final MainPanel mainPanel;
private final TagTree tagTree;
private JMenuItem expandRecursiveMenuItem;
private JMenuItem removeMenuItem;
private JMenuItem removeWithDependenciesMenuItem;
private JMenuItem undoTagMenuItem;
private JMenuItem exportSelectionMenuItem;
private JMenuItem replaceMenuItem;
private JMenuItem replaceNoFillMenuItem;
private JMenuItem replaceWithTagMenuItem;
private JMenuItem rawEditMenuItem;
private JMenuItem jumpToCharacterMenuItem;
private JMenuItem exportJavaSourceMenuItem;
private JMenuItem exportSwfXmlMenuItem;
private JMenuItem importSwfXmlMenuItem;
private JMenuItem closeMenuItem;
private JMenu addTagMenu;
private JMenu moveTagMenu;
private JMenu copyTagMenu;
private JMenu copyTagWithDependenciesMenu;
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::expandRecursiveActionPerformed);
add(expandRecursiveMenuItem);
removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove"));
removeMenuItem.addActionListener((ActionEvent e) -> {
removeItemActionPerformed(e, false);
});
add(removeMenuItem);
removeWithDependenciesMenuItem = new JMenuItem(mainPanel.translate("contextmenu.removeWithDependencies"));
removeWithDependenciesMenuItem.addActionListener((ActionEvent e) -> {
removeItemActionPerformed(e, true);
});
add(removeWithDependenciesMenuItem);
undoTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.undo"));
undoTagMenuItem.addActionListener(this::undoTagActionPerformed);
add(undoTagMenuItem);
exportSelectionMenuItem = new JMenuItem(mainPanel.translate("menu.file.export.selection"));
exportSelectionMenuItem.addActionListener(mainPanel::exportSelectionActionPerformed);
add(exportSelectionMenuItem);
replaceMenuItem = new JMenuItem(mainPanel.translate("button.replace"));
replaceMenuItem.addActionListener(mainPanel::replaceButtonActionPerformed);
add(replaceMenuItem);
replaceNoFillMenuItem = new JMenuItem(mainPanel.translate("button.replaceNoFill"));
replaceNoFillMenuItem.addActionListener(mainPanel::replaceNoFillButtonActionPerformed);
add(replaceNoFillMenuItem);
replaceWithTagMenuItem = new JMenuItem(mainPanel.translate("button.replaceWithTag"));
replaceWithTagMenuItem.addActionListener(this::replaceWithTagActionPerformed);
add(replaceWithTagMenuItem);
rawEditMenuItem = new JMenuItem(mainPanel.translate("contextmenu.rawEdit"));
rawEditMenuItem.addActionListener(this::rawEditActionPerformed);
add(rawEditMenuItem);
jumpToCharacterMenuItem = new JMenuItem(mainPanel.translate("contextmenu.jumpToCharacter"));
jumpToCharacterMenuItem.addActionListener(this::jumpToCharacterActionPerformed);
add(jumpToCharacterMenuItem);
exportJavaSourceMenuItem = new JMenuItem(mainPanel.translate("contextmenu.exportJavaSource"));
exportJavaSourceMenuItem.addActionListener(mainPanel::exportJavaSourceActionPerformed);
add(exportJavaSourceMenuItem);
exportSwfXmlMenuItem = new JMenuItem(mainPanel.translate("contextmenu.exportSwfXml"));
exportSwfXmlMenuItem.addActionListener(mainPanel::exportSwfXmlActionPerformed);
add(exportSwfXmlMenuItem);
importSwfXmlMenuItem = new JMenuItem(mainPanel.translate("contextmenu.importSwfXml"));
importSwfXmlMenuItem.addActionListener(mainPanel::importSwfXmlActionPerformed);
add(importSwfXmlMenuItem);
closeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.closeSwf"));
closeMenuItem.addActionListener(this::closeSwfActionPerformed);
add(closeMenuItem);
addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag"));
add(addTagMenu);
moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag"));
add(moveTagMenu);
copyTagMenu = new JMenu(mainPanel.translate("contextmenu.copyTag"));
add(copyTagMenu);
copyTagWithDependenciesMenu = new JMenu(mainPanel.translate("contextmenu.copyTagWithDependencies"));
add(copyTagWithDependenciesMenu);
openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside"));
add(openSWFInsideTagMenuItem);
openSWFInsideTagMenuItem.addActionListener(this::openSwfInsideActionPerformed);
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(final 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)) {
if (item instanceof TagScript) {
Tag tag = ((TagScript) item).getTag();
if (tag instanceof DoActionTag || tag instanceof DoInitActionTag) {
continue;
}
}
allSelectedIsTagOrFrame = false;
break;
}
}
boolean allSelectedIsTag = true;
for (TreeItem item : items) {
if (!(item instanceof Tag)) {
if (item instanceof TagScript) {
Tag tag = ((TagScript) item).getTag();
if (tag instanceof DoActionTag || tag instanceof DoInitActionTag) {
continue;
}
}
allSelectedIsTag = 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) {
SWF swf = (SWF) item;
// Do not allow to close SWF in bundle
if (swf.swfList != null && swf.swfList.isBundle()) {
allSelectedIsSwf = false;
}
}
}
boolean allSelectedIsInTheSameSwf = true;
SWF singleSwf = null;
for (TreeItem item : items) {
if (item instanceof SWFList) {
allSelectedIsInTheSameSwf = false;
break;
}
if (singleSwf == null) {
singleSwf = item.getSwf();
} else if (singleSwf != item.getSwf()) {
allSelectedIsInTheSameSwf = false;
break;
}
}
expandRecursiveMenuItem.setVisible(false);
removeMenuItem.setVisible(allSelectedIsTagOrFrame);
removeWithDependenciesMenuItem.setVisible(allSelectedIsTagOrFrame);
undoTagMenuItem.setVisible(allSelectedIsTag);
exportSelectionMenuItem.setEnabled(tagTree.hasExportableNodes());
replaceMenuItem.setVisible(false);
replaceNoFillMenuItem.setVisible(false);
replaceWithTagMenuItem.setVisible(false);
rawEditMenuItem.setVisible(false);
jumpToCharacterMenuItem.setVisible(false);
exportJavaSourceMenuItem.setVisible(allSelectedIsSwf);
exportSwfXmlMenuItem.setVisible(allSelectedIsSwf);
importSwfXmlMenuItem.setVisible(allSelectedIsSwf);
closeMenuItem.setVisible(allSelectedIsSwf);
addTagMenu.setVisible(false);
moveTagMenu.setVisible(false);
copyTagMenu.setVisible(false);
copyTagWithDependenciesMenu.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
if (allSelectedIsTag) {
boolean canUndo = false;
for (TreeItem item : items) {
if (item instanceof Tag) {
Tag tag = (Tag) item;
if (tag.canUndo()) {
canUndo = true;
break;
}
}
}
undoTagMenuItem.setEnabled(canUndo);
}
boolean singleSelect = items.size() == 1;
if (singleSelect) {
final TreeItem firstItem = items.get(0);
if (firstItem instanceof CharacterTag) {
replaceWithTagMenuItem.setVisible(true);
}
// replace
if (firstItem instanceof ImageTag && ((ImageTag) firstItem).importSupported()) {
replaceMenuItem.setVisible(true);
}
if (firstItem instanceof ShapeTag) {
replaceMenuItem.setVisible(true);
replaceNoFillMenuItem.setVisible(true);
}
if (firstItem instanceof DefineBinaryDataTag) {
replaceMenuItem.setVisible(true);
}
if (firstItem instanceof DefineSoundTag) {
replaceMenuItem.setVisible(true);
}
addTagMenu.removeAll();
if (firstItem instanceof FolderItem) {
List<Integer> allowedTagTypes;
FolderItem folderItem = (FolderItem) firstItem;
SWF swf = firstItem.getSwf();
if (folderItem.getName().equals(TagTreeModel.FOLDER_OTHERS)) {
TagTreeModel ttm = tagTree.getModel();
for (FolderItem emptyFolder : ttm.getEmptyFolders(swf)) {
JMenu subMenu = new JMenu(emptyFolder.toString());
allowedTagTypes = tagTree.getSwfFolderItemNestedTagIds(emptyFolder.getName(), swf.gfx);
addAddTagMenuItems(allowedTagTypes, subMenu, firstItem);
if (subMenu.getItemCount() > 0) {
addTagMenu.add(subMenu);
}
}
}
allowedTagTypes = tagTree.getSwfFolderItemNestedTagIds(folderItem.getName(), swf.gfx);
addAddTagMenuItems(allowedTagTypes, addTagMenu, firstItem);
} else if (firstItem instanceof Tag) {
List<Integer> allowedTagTypes = tagTree.getNestedTagIds((Tag) firstItem);
addAddTagMenuItems(allowedTagTypes, addTagMenu, firstItem);
} else if (firstItem instanceof Frame) {
List<Integer> allowedTagTypes = tagTree.getFrameNestedTagIds();
addAddTagMenuItems(allowedTagTypes, addTagMenu, firstItem);
}
addTagMenu.setVisible(addTagMenu.getItemCount() > 0);
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(true);
}
}
if (allSelectedIsInTheSameSwf && allSelectedIsTag && swfs.size() > 1) {
moveTagMenu.removeAll();
copyTagMenu.removeAll();
copyTagWithDependenciesMenu.removeAll();
for (SWFList targetSwfList : swfs) {
for (final SWF targetSwf : targetSwfList) {
if (targetSwf != singleSwf) {
JMenuItem swfItem = new JMenuItem(targetSwf.getShortFileName());
swfItem.addActionListener((ActionEvent ae) -> {
moveTagActionPerformed(ae, items, targetSwf);
});
moveTagMenu.add(swfItem);
swfItem = new JMenuItem(targetSwf.getShortFileName());
swfItem.addActionListener((ActionEvent ae) -> {
copyTagActionPerformed(ae, items, targetSwf);
});
copyTagMenu.add(swfItem);
swfItem = new JMenuItem(targetSwf.getShortFileName());
swfItem.addActionListener((ActionEvent ae) -> {
copyTagWithDependenciesActionPerformed(ae, items, targetSwf);
});
copyTagWithDependenciesMenu.add(swfItem);
}
}
}
moveTagMenu.setVisible(true);
copyTagMenu.setVisible(true);
copyTagWithDependenciesMenu.setVisible(true);
}
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);
}
for (TreeItem item : items) {
if (item instanceof Tag) {
if (((Tag) item).isReadOnly()) {
removeMenuItem.setVisible(false);
removeWithDependenciesMenuItem.setVisible(false);
undoTagMenuItem.setVisible(false);
replaceMenuItem.setVisible(false);
replaceNoFillMenuItem.setVisible(false);
replaceWithTagMenuItem.setVisible(false);
rawEditMenuItem.setVisible(false);
jumpToCharacterMenuItem.setVisible(false);
importSwfXmlMenuItem.setVisible(false);
addTagMenu.setVisible(false);
moveTagMenu.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
}
}
}
}
private void addAddTagMenuItems(List<Integer> allowedTagTypes, JMenu addTagMenu, TreeItem item) {
if (allowedTagTypes == null) {
return;
}
for (Integer tagId : allowedTagTypes) {
final Class<?> cl = TagIdClassMap.getClassByTagId(tagId);
JMenuItem tagItem = new JMenuItem(cl.getSimpleName());
tagItem.addActionListener((ActionEvent ae) -> {
addTagActionPerformed(ae, item, cl);
});
addTagMenu.add(tagItem);
}
}
private void addTagActionPerformed(ActionEvent evt, TreeItem firstItem, Class<?> cl) {
try {
SWF swf = firstItem.getSwf();
Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf});
swf.addTag(t, firstItem);
swf.updateCharacters();
mainPanel.refreshTree(swf);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
private int chechUniqueCharacterId(Tag tag) {
if (tag instanceof CharacterTag) {
CharacterTag characterTag = (CharacterTag) tag;
int characterId = characterTag.getCharacterId();
SWF swf = tag.getSwf();
if (swf.getCharacter(characterId) != null) {
int newCharacterId = swf.getNextCharacterId();
characterTag.setCharacterId(newCharacterId);
logger.log(Level.WARNING, "Target SWF already contained chatacter tag with id = {0} => id changed to {1}", new Object[]{characterId, newCharacterId});
return newCharacterId;
}
return characterId;
}
return -1;
}
private void moveTagActionPerformed(ActionEvent evt, List<TreeItem> items, SWF targetSwf) {
SWF sourceSwf = items.get(0).getSwf();
for (TreeItem item : items) {
Tag tag = (Tag) item;
sourceSwf.removeTag(tag);
tag.setSwf(targetSwf, true);
targetSwf.addTag(tag);
chechUniqueCharacterId(tag);
targetSwf.updateCharacters();
tag.setModified(true);
}
sourceSwf.assignExportNamesToSymbols();
targetSwf.assignExportNamesToSymbols();
sourceSwf.assignClassesToSymbols();
targetSwf.assignClassesToSymbols();
sourceSwf.clearImageCache();
targetSwf.clearImageCache();
sourceSwf.updateCharacters();
targetSwf.updateCharacters();
sourceSwf.resetTimelines(sourceSwf);
targetSwf.resetTimelines(targetSwf);
mainPanel.refreshTree(new SWF[]{sourceSwf, targetSwf});
}
private void copyTagActionPerformed(ActionEvent evt, List<TreeItem> items, SWF targetSwf) {
try {
for (TreeItem item : items) {
Tag tag = (Tag) item;
Tag copyTag = tag.cloneTag();
copyTag.setSwf(targetSwf, true);
targetSwf.addTag(copyTag);
chechUniqueCharacterId(copyTag);
targetSwf.updateCharacters();
copyTag.setModified(true);
}
targetSwf.assignExportNamesToSymbols();
targetSwf.assignClassesToSymbols();
targetSwf.clearImageCache();
targetSwf.updateCharacters();
mainPanel.refreshTree(targetSwf);
} catch (IOException | InterruptedException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
private void copyTagWithDependenciesActionPerformed(ActionEvent evt, List<TreeItem> items, SWF targetSwf) {
try {
SWF sourceSwf = items.get(0).getSwf();
for (TreeItem item : items) {
Set<Tag> copiedTags = new HashSet<>();
Set<Tag> newTags = new HashSet<>();
Set<Integer> needed = new LinkedHashSet<>();
Map<Integer, Integer> changedCharacterIds = new HashMap<>();
Tag tag = (Tag) item;
tag.getNeededCharactersDeep(needed);
Tag copyTag;
List<Integer> neededList = new ArrayList<>();
for (Integer characterId : needed) {
neededList.add(characterId);
}
// first add dependencies in reverse order
for (int i = neededList.size() - 1; i >= 0; i--) {
int characterId = neededList.get(i);
CharacterTag neededTag = sourceSwf.getCharacter(characterId);
if (!copiedTags.contains(neededTag)) {
copyTag = neededTag.cloneTag();
copyTag.setSwf(targetSwf, true);
targetSwf.addTag(copyTag);
int oldCharacterId = neededTag.getCharacterId();
int newCharacterId = chechUniqueCharacterId(copyTag);
changedCharacterIds.put(oldCharacterId, newCharacterId);
targetSwf.updateCharacters();
targetSwf.getCharacters(); // force rebuild character id cache
copyTag.setModified(true);
copiedTags.add(neededTag);
newTags.add(copyTag);
}
}
copyTag = tag.cloneTag();
copyTag.setSwf(targetSwf, true);
targetSwf.addTag(copyTag);
if (tag instanceof CharacterTag) {
CharacterTag characterTag = (CharacterTag) copyTag;
int oldCharacterId = characterTag.getCharacterId();
int newCharacterId = chechUniqueCharacterId(copyTag);
changedCharacterIds.put(oldCharacterId, newCharacterId);
}
targetSwf.updateCharacters();
targetSwf.getCharacters(); // force rebuild character id cache
copyTag.setModified(true);
copiedTags.add(tag);
newTags.add(copyTag);
for (int oldCharacterId : changedCharacterIds.keySet()) {
int newCharacterId = changedCharacterIds.get(oldCharacterId);
for (Tag newTag : newTags) {
// todo: avoid double replaces
newTag.replaceCharacter(oldCharacterId, newCharacterId);
}
}
}
targetSwf.assignExportNamesToSymbols();
targetSwf.assignClassesToSymbols();
targetSwf.clearImageCache();
targetSwf.updateCharacters();
mainPanel.refreshTree(targetSwf);
} catch (IOException | InterruptedException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
private void openSwfInsideActionPerformed(ActionEvent evt) {
List<TreeItem> sel = tagTree.getSelected();
List<DefineBinaryDataTag> binaryDatas = new ArrayList<>();
for (TreeItem item : sel) {
DefineBinaryDataTag binaryData = (DefineBinaryDataTag) item;
if (binaryData.isSwfData()) {
binaryDatas.add((DefineBinaryDataTag) item);
}
}
mainPanel.loadFromBinaryTag(binaryDatas);
}
private void replaceWithTagActionPerformed(ActionEvent evt) {
TreeItem itemr = tagTree.getCurrentTreeItem();
if (itemr == null) {
return;
}
SWF swf = itemr.getSwf();
CharacterTag characterTag = (CharacterTag) itemr;
int characterId = characterTag.getCharacterId();
ReplaceCharacterDialog replaceCharacterDialog = new ReplaceCharacterDialog();
if (replaceCharacterDialog.showDialog(swf, characterId) == AppDialog.OK_OPTION) {
int newCharacterId = replaceCharacterDialog.getCharacterId();
swf.replaceCharacterTags(characterTag, newCharacterId);
mainPanel.refreshTree(swf);
}
}
private void rawEditActionPerformed(ActionEvent evt) {
TreeItem itemr = tagTree.getCurrentTreeItem();
if (itemr == null) {
return;
}
mainPanel.showGenericTag((Tag) itemr);
}
private void jumpToCharacterActionPerformed(ActionEvent evt) {
TreeItem itemj = tagTree.getCurrentTreeItem();
if (itemj == null || !(itemj instanceof CharacterIdTag)) {
return;
}
CharacterIdTag characterIdTag = (CharacterIdTag) itemj;
mainPanel.setTagTreeSelectedNode(itemj.getSwf().getCharacter(characterIdTag.getCharacterId()));
}
private void expandRecursiveActionPerformed(ActionEvent evt) {
TreePath path = tagTree.getSelectionPath();
if (path == null) {
return;
}
View.expandTreeNodes(tagTree, path, true);
}
private void removeItemActionPerformed(ActionEvent evt, boolean removeDependencies) {
List<TreeItem> sel = tagTree.getSelected();
List<Tag> tagsToRemove = new ArrayList<>();
for (TreeItem item : sel) {
if (item instanceof Tag) {
tagsToRemove.add((Tag) item);
} else if (item instanceof TagScript) {
tagsToRemove.add(((TagScript) item).getTag());
} else if (item instanceof Frame) {
Frame frameNode = (Frame) item;
Frame frame = frameNode.timeline.getFrame(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);
}
}
}
if (tagsToRemove.size() > 0) {
String confirmationMessage;
if (tagsToRemove.size() == 1) {
Tag tag = tagsToRemove.get(0);
confirmationMessage = mainPanel.translate("message.confirm.remove").replace("%item%", tag.toString());
} else {
confirmationMessage = mainPanel.translate("message.confirm.removemultiple").replace("%count%", Integer.toString(tagsToRemove.size()));
}
if (View.showConfirmDialog(this, confirmationMessage, mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
Map<SWF, List<Tag>> tagsToRemoveBySwf = new HashMap<>();
for (Tag tag : tagsToRemove) {
SWF swf = tag.getSwf();
if (!tagsToRemoveBySwf.containsKey(swf)) {
tagsToRemoveBySwf.put(swf, new ArrayList<>());
}
tagsToRemoveBySwf.get(swf).add(tag);
}
for (SWF swf : tagsToRemoveBySwf.keySet()) {
swf.removeTags(tagsToRemoveBySwf.get(swf), removeDependencies);
}
mainPanel.refreshTree();
}
}
}
private void undoTagActionPerformed(ActionEvent evt) {
List<TreeItem> sel = tagTree.getSelected();
for (TreeItem item : sel) {
if (item instanceof Tag) {
try {
Tag tag = (Tag) item;
tag.undo();
tag.getSwf().clearAllCache();
tagTree.getModel().updateNode(item);
} catch (InterruptedException | IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
}
mainPanel.repaintTree();
}
private void closeSwfActionPerformed(ActionEvent evt) {
List<TreeItem> sel = tagTree.getSelected();
for (TreeItem item : sel) {
if (item instanceof SWF) {
SWF swf = (SWF) item;
if (swf.binaryData != null) {
// embedded swf
swf.binaryData.innerSwf = null;
swf.clearTagSwfs();
mainPanel.refreshTree();
} else {
Main.closeFile(swf.swfList);
}
} else if (item instanceof SWFList) {
Main.closeFile((SWFList) item);
}
}
}
}