Added Adding tag "inside" allows setting character id to original when possible

Fixed
- Add tag (before/after/inside) refactored to more meaningful menus
- Add tag renamed to Add tag inside
This commit is contained in:
Jindra Petřík
2022-10-31 18:29:01 +01:00
parent 8fe57ca6f1
commit 9269cb2bde
9 changed files with 352 additions and 197 deletions

View File

@@ -5,12 +5,17 @@ All notable changes to this project will be documented in this file.
### Added
- Allow add tag after header context menu
- DefineScalingGrid has icon
- Adding tag "inside" allows setting character id to original when possible
### Fixed
- Do not show option to Show in taglist on resource view folders
- Disallow add tag before header context menu
- Context menu on tags mapped to other characters like DefineScalingGrid
- Add tag before/after for frame selection position
- Add tag (before/after/inside) refactored to more meaningful menus
### Changed
- Add tag renamed to Add tag inside
## [16.0.0] - 2022-10-30
### Added

View File

@@ -307,7 +307,7 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
return knownTagInfosByName;
}
private static void addTagInfo(Map<Integer, TagTypeInfo> map, Map<String, TagTypeInfo> map2, int id, Class cls, String name) {
map.put(id, new TagTypeInfo(id, cls, name));
map2.put(name, new TagTypeInfo(id, cls, name));

View File

@@ -78,6 +78,8 @@ public class SelectTagPositionDialog extends AppDialog {
private Timelined selectedTimelined = null;
private boolean allowInsideSprites;
private boolean selectNext;
private static class MyTreeNode implements TreeNode {
private final List<TreeNode> children = new ArrayList<>();
@@ -242,9 +244,14 @@ public class SelectTagPositionDialog extends AppDialog {
List<Object> subPath = new ArrayList<>(path);
subPath.add(node);
List<Object> nextPath = new ArrayList<>(path);
if (i + 1 < root.getChildCount()) {
nextPath.add(root.getChildAt(i + 1));
}
if (timelined == selectedTimelined && ((node.getData() == selectedTag))) {
selectPath(subPath);
selectPath(selectNext ? nextPath : subPath);
return;
}
if (timelined == selectedTimelined && (node.getData() instanceof MyTimelineEnd) && selectedTag == null) {
@@ -252,7 +259,7 @@ public class SelectTagPositionDialog extends AppDialog {
return;
}
if ((selectedTimelined instanceof DefineSpriteTag) && !allowInsideSprites && node.getData() == selectedTimelined) {
selectPath(subPath);
selectPath(nextPath);
return;
}
@@ -266,7 +273,7 @@ public class SelectTagPositionDialog extends AppDialog {
}
public SelectTagPositionDialog(Window parent, SWF swf, boolean allowInsideSprites) {
this(parent, swf, null, null, allowInsideSprites);
this(parent, swf, null, null, allowInsideSprites, false);
}
private static class PositionTreeCellRenderer extends DefaultTreeCellRenderer {
@@ -307,12 +314,13 @@ public class SelectTagPositionDialog extends AppDialog {
}
}
public SelectTagPositionDialog(Window parent, SWF swf, Tag selectedTag, Timelined selectedTimelined, boolean allowInsideSprites) {
public SelectTagPositionDialog(Window parent, SWF swf, Tag selectedTag, Timelined selectedTimelined, boolean allowInsideSprites, boolean selectNext) {
super(parent);
this.swf = swf;
this.selectedTag = selectedTag;
this.selectedTimelined = selectedTimelined;
this.allowInsideSprites = allowInsideSprites;
this.selectNext = selectNext;
setTitle(translate("dialog.title"));
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
Container cnt = getContentPane();

View File

@@ -893,3 +893,6 @@ Changes you make won't be saved unless you use the "Save as" button.\r\n\
This is usually caused by opening file in binary search mode,\r\n\
the file has probably unknown extension and then saving cannot be done because\r\n\
the file format is unknown.
#after 16.0.0
contextmenu.addTagInside = Add tag inside

View File

@@ -862,4 +862,7 @@ warning.readonly = Soubor "%file%" je na\u010dten\u00fd v re\u017eimu JEN KE \u0
Zm\u011bny kter\u00e9 provedete nebudou ulo\u017eeny dokud nepou\u017eijete tla\u010d\u00edtko "Ulo\u017eit jako".\r\n\
Toto je obvykle zp\u016fsobeno otev\u00edr\u00e1n\u00edm souboru v re\u017eimu bin\u00e1rn\u00edho vyhled\u00e1v\u00e1n\u00ed,\r\n\
soubor m\u00e1 pravd\u011bpodobn\u011b nezn\u00e1mou p\u0159\u00edponu a tak ulo\u017een\u00ed nen\u00ed mo\u017en\u00e9 proto\u017ee\r\n\
form\u00e1t souboru nen\u00ed zn\u00e1m.
form\u00e1t souboru nen\u00ed zn\u00e1m.
#after 16.0.0
contextmenu.addTagInside = P\u0159idat tag dovnit\u0159

View File

@@ -20,26 +20,7 @@ import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.gui.MainPanel;
import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTree;
import static com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTree.getSelection;
import com.jpexs.decompiler.flash.tags.DefineScalingGridTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.FrameLabelTag;
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
import com.jpexs.decompiler.flash.tags.PlaceObject3Tag;
import com.jpexs.decompiler.flash.tags.PlaceObject4Tag;
import com.jpexs.decompiler.flash.tags.PlaceObjectTag;
import com.jpexs.decompiler.flash.tags.RemoveObject2Tag;
import com.jpexs.decompiler.flash.tags.RemoveObjectTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.StartSound2Tag;
import com.jpexs.decompiler.flash.tags.StartSoundTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -61,29 +42,6 @@ public class TagListTree extends AbstractTagTree {
@Override
public TagListTreeModel getModel() {
return (TagListTreeModel) super.getModel();
}
}
@Override
public List<Integer> getNestedTagIds(Tag obj) {
if (obj instanceof DefineSpriteTag) {
return getSpriteNestedTagIds();
}
return new ArrayList<>();
}
private List<Integer> getSpriteNestedTagIds() {
return Arrays.asList(PlaceObjectTag.ID, PlaceObject2Tag.ID, PlaceObject3Tag.ID, PlaceObject4Tag.ID,
RemoveObjectTag.ID, RemoveObject2Tag.ID, ShowFrameTag.ID, FrameLabelTag.ID,
StartSoundTag.ID, StartSound2Tag.ID, VideoFrameTag.ID,
SoundStreamBlockTag.ID, SoundStreamHeadTag.ID, SoundStreamHead2Tag.ID,
DefineScalingGridTag.ID); //scaling grid? FIXME?
}
@Override
public List<Integer> getFrameNestedTagIds(boolean inSprite) {
if (inSprite) {
return getSpriteNestedTagIds();
}
return null; //null = all possible tags
}
}

View File

@@ -31,10 +31,20 @@ import com.jpexs.decompiler.flash.gui.TreeNodeType;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.helpers.CollectionChangedEvent;
import com.jpexs.decompiler.flash.iggy.conversion.IggySwfBundle;
import com.jpexs.decompiler.flash.tags.CSMTextSettingsTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineButtonCxformTag;
import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag;
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.DefineFont3Tag;
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineFontAlignZonesTag;
import com.jpexs.decompiler.flash.tags.DefineFontInfo2Tag;
import com.jpexs.decompiler.flash.tags.DefineFontInfoTag;
import com.jpexs.decompiler.flash.tags.DefineFontNameTag;
import com.jpexs.decompiler.flash.tags.DefineFontTag;
import com.jpexs.decompiler.flash.tags.DefineScalingGridTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
@@ -44,14 +54,27 @@ import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.EndTag;
import com.jpexs.decompiler.flash.tags.FileAttributesTag;
import com.jpexs.decompiler.flash.tags.FrameLabelTag;
import com.jpexs.decompiler.flash.tags.JPEGTablesTag;
import com.jpexs.decompiler.flash.tags.MetadataTag;
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
import com.jpexs.decompiler.flash.tags.PlaceObject3Tag;
import com.jpexs.decompiler.flash.tags.PlaceObject4Tag;
import com.jpexs.decompiler.flash.tags.PlaceObjectTag;
import com.jpexs.decompiler.flash.tags.RemoveObject2Tag;
import com.jpexs.decompiler.flash.tags.RemoveObjectTag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.StartSound2Tag;
import com.jpexs.decompiler.flash.tags.StartSoundTag;
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.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
@@ -500,9 +523,14 @@ public abstract class AbstractTagTree extends JTree {
}
}
public abstract List<Integer> getNestedTagIds(Tag obj);
public abstract List<Integer> getFrameNestedTagIds(boolean inSprite);
public static List<Integer> getFrameNestedTagIds() {
return Arrays.asList(PlaceObjectTag.ID, PlaceObject2Tag.ID, PlaceObject3Tag.ID, PlaceObject4Tag.ID,
RemoveObjectTag.ID, RemoveObject2Tag.ID, ShowFrameTag.ID, FrameLabelTag.ID,
StartSoundTag.ID, StartSound2Tag.ID, VideoFrameTag.ID,
SoundStreamBlockTag.ID, SoundStreamHeadTag.ID, SoundStreamHead2Tag.ID
);
}
public TreeItem getCurrentTreeItem() {
TreeItem item = (TreeItem) getLastSelectedPathComponent();
@@ -621,4 +649,23 @@ public abstract class AbstractTagTree extends JTree {
return TreeNodeType.FOLDER;
}
public static List<Integer> getMappedTagIdsForClass(Class<?> cls) {
if (cls == DefineSpriteTag.class) {
return Arrays.asList(DefineScalingGridTag.ID, DoInitActionTag.ID);
}
if (FontTag.class.isAssignableFrom(cls)) {
return Arrays.asList(DefineFontNameTag.ID, DefineFontAlignZonesTag.ID, DefineFontInfoTag.ID, DefineFontInfo2Tag.ID);
}
if (TextTag.class.isAssignableFrom(cls)) {
return Arrays.asList(CSMTextSettingsTag.ID);
}
if (cls == DefineButtonTag.class) {
return Arrays.asList(DefineButtonCxformTag.ID, DefineButtonSoundTag.ID, DefineScalingGridTag.ID);
}
if (cls == DefineButton2Tag.class) {
return Arrays.asList(DefineButtonSoundTag.ID, DefineScalingGridTag.ID);
}
return new ArrayList<>();
}
}

View File

@@ -295,41 +295,7 @@ public class TagTree extends AbstractTagTree {
return ret;
}
@Override
public List<Integer> getFrameNestedTagIds(boolean inSprite) {
return Arrays.asList(PlaceObjectTag.ID, PlaceObject2Tag.ID, PlaceObject3Tag.ID, PlaceObject4Tag.ID,
RemoveObjectTag.ID, RemoveObject2Tag.ID, FrameLabelTag.ID,
StartSoundTag.ID, StartSound2Tag.ID, VideoFrameTag.ID,
SoundStreamBlockTag.ID, SoundStreamHeadTag.ID, SoundStreamHead2Tag.ID);
}
@Override
public List<Integer> getNestedTagIds(Tag obj) {
if (obj instanceof DefineSpriteTag) {
return Arrays.asList(PlaceObjectTag.ID, PlaceObject2Tag.ID, PlaceObject3Tag.ID, PlaceObject4Tag.ID,
RemoveObjectTag.ID, RemoveObject2Tag.ID, ShowFrameTag.ID, FrameLabelTag.ID,
StartSoundTag.ID, StartSound2Tag.ID, VideoFrameTag.ID,
SoundStreamBlockTag.ID, SoundStreamHeadTag.ID, SoundStreamHead2Tag.ID,
DefineScalingGridTag.ID);
}
if (obj instanceof FontTag) {
return Arrays.asList(DefineFontNameTag.ID, DefineFontAlignZonesTag.ID, DefineFontInfoTag.ID, DefineFontInfo2Tag.ID);
}
if (obj instanceof TextTag) {
return Arrays.asList(CSMTextSettingsTag.ID);
}
if (obj instanceof DefineButtonTag) {
return Arrays.asList(DefineButtonCxformTag.ID, DefineButtonSoundTag.ID, DefineScalingGridTag.ID);
}
if (obj instanceof DefineButton2Tag) {
return Arrays.asList(DefineButtonSoundTag.ID, DefineScalingGridTag.ID);
}
return new ArrayList<>();
}
@Override
public List<TreeItem> getSelection(SWF swf) {
List<TreeItem> sel;

View File

@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser;
import com.jpexs.decompiler.flash.amf.amf3.ListSet;
import com.jpexs.decompiler.flash.gui.AppDialog;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.SelectTagPositionDialog;
@@ -61,6 +62,7 @@ import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.StartSoundTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.TagTypeInfo;
import com.jpexs.decompiler.flash.tags.UnknownTag;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
@@ -154,7 +156,7 @@ public class TagTreeContextMenu extends JPopupMenu {
private JMenuItem closeMenuItem;
private JMenu addTagMenu;
private JMenu addTagInsideMenu;
private JMenu addTagBeforeMenu;
@@ -207,22 +209,22 @@ public class TagTreeContextMenu extends JPopupMenu {
removeWithDependenciesMenuItem.addActionListener((ActionEvent e) -> {
removeItemActionPerformed(e, true);
});
removeWithDependenciesMenuItem.setIcon(View.getIcon("remove16"));
add(removeWithDependenciesMenuItem);
removeWithDependenciesMenuItem.setIcon(View.getIcon("remove16"));
add(removeWithDependenciesMenuItem);
undoTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.undo"));
undoTagMenuItem.addActionListener(this::undoTagActionPerformed);
undoTagMenuItem.setIcon(View.getIcon("undo16"));
undoTagMenuItem.setIcon(View.getIcon("undo16"));
add(undoTagMenuItem);
exportSelectionMenuItem = new JMenuItem(mainPanel.translate("menu.file.export.selection"));
exportSelectionMenuItem.addActionListener(mainPanel::exportSelectionActionPerformed);
exportSelectionMenuItem.setIcon(View.getIcon("exportsel16"));
exportSelectionMenuItem.setIcon(View.getIcon("exportsel16"));
add(exportSelectionMenuItem);
replaceMenuItem = new JMenuItem(mainPanel.translate("button.replace"));
replaceMenuItem.addActionListener(mainPanel::replaceButtonActionPerformed);
replaceMenuItem.setIcon(View.getIcon("replaceitem16"));
replaceMenuItem.setIcon(View.getIcon("replaceitem16"));
add(replaceMenuItem);
replaceNoFillMenuItem = new JMenuItem(mainPanel.translate("button.replaceNoFill"));
@@ -275,9 +277,9 @@ public class TagTreeContextMenu extends JPopupMenu {
showInTagListViewTagMenuItem.setIcon(View.getIcon("taglist16"));
add(showInTagListViewTagMenuItem);
addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag"));
addTagMenu.setIcon(View.getIcon("addtag16"));
add(addTagMenu);
addTagInsideMenu = new JMenu(mainPanel.translate("contextmenu.addTagInside"));
addTagInsideMenu.setIcon(View.getIcon("addtag16"));
add(addTagInsideMenu);
addTagBeforeMenu = new JMenu(mainPanel.translate("contextmenu.addTagBefore"));
addTagBeforeMenu.setIcon(View.getIcon("addtag16"));
@@ -291,7 +293,7 @@ public class TagTreeContextMenu extends JPopupMenu {
cloneTagMenuItem.addActionListener(this::cloneTagActionPerformed);
cloneTagMenuItem.setIcon(View.getIcon("copy16"));
add(cloneTagMenuItem);
moveTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.moveTagAround"));
moveTagMenuItem.addActionListener(this::moveTagActionPerformed);
moveTagMenuItem.setIcon(View.getIcon("move16"));
@@ -311,9 +313,9 @@ public class TagTreeContextMenu extends JPopupMenu {
openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside"));
openSWFInsideTagMenuItem.setIcon(View.getIcon("openinside16"));
openSWFInsideTagMenuItem.addActionListener(this::openSwfInsideActionPerformed);
openSWFInsideTagMenuItem.addActionListener(this::openSwfInsideActionPerformed);
add(openSWFInsideTagMenuItem);
addAs12ScriptMenuItem = new JMenuItem(mainPanel.translate("contextmenu.addScript"));
addAs12ScriptMenuItem.addActionListener(this::addAs12ScriptActionPerformed);
addAs12ScriptMenuItem.setIcon(View.getIcon("scriptadd16"));
@@ -579,7 +581,7 @@ public class TagTreeContextMenu extends JPopupMenu {
exportSwfXmlMenuItem.setVisible(allSelectedIsSwf);
importSwfXmlMenuItem.setVisible(allSelectedIsSwf);
closeMenuItem.setVisible(allSelectedIsSwf);
addTagMenu.setVisible(false);
addTagInsideMenu.setVisible(false);
addTagBeforeMenu.setVisible(false);
addTagAfterMenu.setVisible(false);
moveTagToMenu.setVisible(false);
@@ -663,28 +665,54 @@ public class TagTreeContextMenu extends JPopupMenu {
replaceWithTagMenuItem.setVisible(true);
replaceRefsWithTagMenuItem.setVisible(true);
}
addTagMenu.removeAll();
if (firstItem instanceof FolderItem) {
FolderItem folderItem = (FolderItem) firstItem;
if (folderItem.getName().equals(TagTreeModel.FOLDER_FRAMES)) {
addFramesMenuItem.setVisible(true);
TreeItem parent = (TreeItem) tree.getModel().getTreePath(firstItem).getParentPath().getLastPathComponent();
boolean parentIsFolder = parent instanceof FolderItem;
boolean parentIsTopLevelFrame = false;
if (parent instanceof Frame) {
if (((Frame)parent).timeline.timelined instanceof SWF) {
parentIsTopLevelFrame = true;
}
}
addAddTagMenuItems(getAllowedTagTypes(firstItem), addTagMenu, firstItem, this::addTagActionPerformed);
addTagMenu.setVisible(addTagMenu.getItemCount() > 0);
TreeItem parent = (TreeItem) tree.getModel().getTreePath(firstItem).getParentPath().getLastPathComponent();
addTagBeforeMenu.removeAll();
if (!isFolder && !(firstItem instanceof HeaderItem)) {
addAddTagMenuItems(getAllowedTagTypes(parent), addTagBeforeMenu, firstItem, this::addTagBeforeActionPerformed);
}
boolean addAllTags = false;
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && parentIsTopLevelFrame) {
addAllTags = true;
}
boolean addInsideAddAllTags = false;
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && (firstItem instanceof Frame))
{
if (((Frame)firstItem).timeline.timelined instanceof SWF) {
addInsideAddAllTags = true;
}
}
addTagInsideMenu.removeAll();
addAddTagInsideMenuItems(firstItem);
addTagInsideMenu.setVisible(addTagInsideMenu.getItemCount() > 0);
addTagBeforeMenu.removeAll();
addAddTagBeforeAfterMenuItems(true, addTagBeforeMenu, firstItem, this::addTagBeforeActionPerformed);
addTagBeforeMenu.setVisible(addTagBeforeMenu.getItemCount() > 0);
addTagAfterMenu.removeAll();
if (!isFolder) {
addAddTagMenuItems(getAllowedTagTypes(parent), addTagAfterMenu, firstItem, this::addTagAfterActionPerformed);
}
addAddTagBeforeAfterMenuItems(false, addTagAfterMenu, firstItem, this::addTagAfterActionPerformed);
//addAddTagMenuItems(getAllowedTagTypes(parent), addTagAfterMenu, firstItem, this::addTagAfterActionPerformed);
/*JMenu othersMenu = new JMenu(AppStrings.translate("node.others"));
othersMenu.setIcon(View.getIcon("folder16"));
addAddTagMenuItems(null, othersMenu, firstItem, this::addTagAfterActionPerformed);
addTagAfterMenu.add(othersMenu);*/
addTagAfterMenu.setVisible(addTagAfterMenu.getItemCount() > 0);
if (tree.getModel().getChildCount(firstItem) > 0) {
@@ -707,14 +735,14 @@ public class TagTreeContextMenu extends JPopupMenu {
addFramesBeforeMenuItem.setVisible(true);
addFramesAfterMenuItem.setVisible(true);
}
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && !(firstItem instanceof ShowFrameTag)) {
showInResourcesViewTagMenuItem.setVisible(true);
}
}
if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES && !isFolder) {
showInTagListViewTagMenuItem.setVisible(true);
}
}
}
if (allSelectedIsInTheSameSwf && allSelectedIsTag && swfs.size() > 1) {
@@ -778,53 +806,169 @@ public class TagTreeContextMenu extends JPopupMenu {
rawEditMenuItem.setVisible(false);
jumpToCharacterMenuItem.setVisible(false);
importSwfXmlMenuItem.setVisible(false);
addTagMenu.setVisible(false);
addTagInsideMenu.setVisible(false);
moveTagToMenu.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
}
}
}
}
}
private List<Integer> getAllowedTagTypes(TreeItem item) {
if (item instanceof FolderItem) {
FolderItem folderItem = (FolderItem) item;
SWF swf = item.getSwf();
if (swf == null) { //root
return new ArrayList<>();
}
return ((TagTree) getTree()).getSwfFolderItemNestedTagIds(folderItem.getName(), swf.gfx);
} else if (item instanceof Tag) {
return getTree().getNestedTagIds((Tag) item);
} else if (item instanceof Frame) {
return getTree().getFrameNestedTagIds(((Frame) item).timeline.timelined instanceof DefineSpriteTag);
} else if (item instanceof SWF) {
return null;
}
return new ArrayList<>();
}
private interface AddTagActionLisener {
private interface AddTagActionListener {
void call(ActionEvent evt, TreeItem item, Class<?> cl);
}
private void addAddTagMenuFolder(JMenu addTagMenu, String folder, boolean gfx, TreeItem item, AddTagActionLisener listener) {
private void addAddTagMenuFolder(JMenu addTagMenu, String folder, boolean gfx, TreeItem item, AddTagActionListener listener) {
String folderTranslated = AppStrings.translate("node." + folder);
JMenu folderMenu = new JMenu(folderTranslated);
folderMenu.setIcon(View.getIcon("folder" + folder.toLowerCase(Locale.ENGLISH) + "16"));
List<Integer> allowedTagTypes = TagTree.getSwfFolderItemNestedTagIds(folder, gfx);
if (allowedTagTypes.isEmpty()) {
Map<Integer, TagTypeInfo> classes = Tag.getKnownClasses();
List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(folder, gfx));
Set<Integer> mappedTagTypes = new LinkedHashSet<>();
for (int i: allowedTagTypes) {
mappedTagTypes.addAll(AbstractTagTree.getMappedTagIdsForClass(classes.get(i).getCls()));
}
if (allowedTagTypes.isEmpty() && mappedTagTypes.isEmpty()) {
return;
}
addAddTagMenuItems(allowedTagTypes, folderMenu, item, listener);
addAddTagMenuItems(allowedTagTypes, folderMenu, item, listener);
if (!allowedTagTypes.isEmpty() && !mappedTagTypes.isEmpty()) {
folderMenu.addSeparator();
}
addAddTagMenuItems(new ArrayList<Integer>(mappedTagTypes), folderMenu, item, listener);
addTagMenu.add(folderMenu);
}
private void addAddTagInsideMenuItems(TreeItem item)
{
AddTagActionListener listener = this::addTagInsideActionPerformed;
Map<Integer, TagTypeInfo> classes = Tag.getKnownClasses();
boolean gfx = mainPanel.getCurrentSwf().gfx;
if (item instanceof SWF) {
addAddTagMenuItems(null, addTagInsideMenu, item, listener);
return;
}
if (item instanceof DefineSpriteTag) {
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener);
addTagInsideMenu.addSeparator();
addAddTagMenuItems(AbstractTagTree.getMappedTagIdsForClass(DefineSpriteTag.class), addTagInsideMenu, item, listener);
return;
}
if (item instanceof Frame) {
Frame frame = (Frame) item;
boolean insideSprite = frame.timeline.timelined instanceof DefineSpriteTag;
if (insideSprite) {
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener);
} else {
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST) {
addAddTagMenuItems(null, addTagInsideMenu, item, listener);
return;
}
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener);
if (!insideSprite) {
addTagInsideMenu.addSeparator();
addTagInsideMenu.add(createOthersMenu(item, listener));
}
}
return;
}
if (item instanceof FolderItem) {
List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem)item).getName(), gfx));
Set<Integer> mappedTagTypes = new LinkedHashSet<>();
for (int i: allowedTagTypes) {
mappedTagTypes.addAll(AbstractTagTree.getMappedTagIdsForClass(classes.get(i).getCls()));
}
addAddTagMenuItems(allowedTagTypes, addTagInsideMenu, item, listener);
if (!allowedTagTypes.isEmpty() && !mappedTagTypes.isEmpty()) {
addTagInsideMenu.addSeparator();
}
addAddTagMenuItems(new ArrayList<Integer>(mappedTagTypes), addTagInsideMenu, item, listener);
return;
}
private void addAddTagMenuItems(List<Integer> allowedTagTypes, JMenu addTagMenu, TreeItem item, AddTagActionLisener listener) {
if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES) {
List<Integer> mapped = AbstractTagTree.getMappedTagIdsForClass(item.getClass());
addAddTagMenuItems(mapped, addTagInsideMenu, item, listener);
}
}
private void addAddTagBeforeAfterMenuItems(boolean before, JMenu addTagMenu, TreeItem item, AddTagActionListener listener) {
TreeItem parent = (TreeItem) getTree().getModel().getTreePath(item).getParentPath().getLastPathComponent();
Map<Integer, TagTypeInfo> classes = Tag.getKnownClasses();
boolean gfx = mainPanel.getCurrentSwf().gfx;
boolean insideFrame = false;
boolean insideSprite = false;
if (item instanceof Frame) {
insideFrame = true;
Frame frame = (Frame) item;
insideSprite = (frame.timeline.timelined instanceof DefineSpriteTag);
}
if (parent instanceof Frame) {
insideFrame = true;
Frame frame = (Frame) parent;
insideSprite = (frame.timeline.timelined instanceof DefineSpriteTag);
}
if (insideFrame) {
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && !insideSprite) {
addAddTagMenuItems(null, addTagMenu, item, listener);
return;
}
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagMenu, item, listener);
if (!insideSprite) {
addTagMenu.addSeparator();
addTagMenu.add(createOthersMenu(item, listener));
}
return;
}
if (parent instanceof FolderItem) {
List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem)parent).getName(), gfx));
Set<Integer> mappedTagTypes = new LinkedHashSet<>();
for (int i: allowedTagTypes) {
mappedTagTypes.addAll(AbstractTagTree.getMappedTagIdsForClass(classes.get(i).getCls()));
}
addAddTagMenuItems(allowedTagTypes, addTagMenu, item, listener);
if (!allowedTagTypes.isEmpty() && !mappedTagTypes.isEmpty()) {
addTagMenu.addSeparator();
}
addAddTagMenuItems(new ArrayList<Integer>(mappedTagTypes), addTagMenu, item, listener);
if (!allowedTagTypes.isEmpty() && !mappedTagTypes.isEmpty()) {
addTagMenu.addSeparator();
}
addTagMenu.add(createOthersMenu(item, listener));
return;
}
if ((item instanceof HeaderItem) && !before) {
addAddTagMenuItems(null, addTagMenu, item, listener);
}
}
private JMenu createOthersMenu(TreeItem item, AddTagActionListener listener) {
JMenu othersMenu = new JMenu(AppStrings.translate("node.others"));
othersMenu.setIcon(View.getIcon("folder16"));
addAddTagMenuItems(null, othersMenu, item, listener);
return othersMenu;
}
private void addAddTagMenuItems(List<Integer> allowedTagTypes, JMenu addTagMenu, TreeItem item, AddTagActionListener listener) {
if (allowedTagTypes == null) {
boolean gfx = mainPanel.getCurrentSwf().gfx;
@@ -863,9 +1007,9 @@ public class TagTreeContextMenu extends JPopupMenu {
});
addTagMenu.add(tagItem);
}
}
private void addTagActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) {
}
private void addTagInsideActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) {
int id = -1;
try {
id = cl.getDeclaredField("ID").getInt(null);
@@ -891,26 +1035,44 @@ public class TagTreeContextMenu extends JPopupMenu {
case EndTag.ID:
allowedInsideSprite = true;
}
SWF swf = item.getSwf();
SWF swf = item.getSwf();
Timelined selectedTimelined = null;
Tag selectedTag = null;
boolean selectNext = false;
if (item instanceof DefineSpriteTag) {
selectedTimelined = (DefineSpriteTag) item;
}
if (item instanceof Frame) {
} else if (item instanceof Frame) {
Frame frame = (Frame) item;
selectedTimelined = frame.timeline.timelined;
if (!frame.allInnerTags.isEmpty()){
if (!frame.allInnerTags.isEmpty()) {
selectedTag = frame.allInnerTags.get(frame.allInnerTags.size() - 1);
}
} else if (item instanceof FolderItem) {
selectedTimelined = item.getSwf();
} else if (item instanceof Tag) {
selectedTimelined = item.getSwf(); //mapped tags
selectedTag = (Tag) item;
selectNext = true;
} else if (item instanceof SWF) {
selectedTimelined = (SWF) item;
}
SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), swf, selectedTag, selectedTimelined, allowedInsideSprite);
SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), swf, selectedTag, selectedTimelined, allowedInsideSprite, selectNext);
if (selectPositionDialog.showDialog() == AppDialog.OK_OPTION) {
selectedTimelined = selectPositionDialog.getSelectedTimelined();
selectedTag = selectPositionDialog.getSelectedTag();
try {
Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf});
//it's "inside", add mapping
if (AbstractTagTree.getMappedTagIdsForClass(item.getClass()).contains(id)) {
if ((t instanceof CharacterIdTag)&&(!(t instanceof CharacterTag))&&(item instanceof CharacterTag)) {
CharacterIdTag chit = (CharacterIdTag) t;
chit.setCharacterId(((CharacterTag)item).getCharacterId());
}
}
t.setTimelined(selectedTimelined);
if (selectedTag == null) {
selectedTimelined.addTag(t);
@@ -920,10 +1082,11 @@ public class TagTreeContextMenu extends JPopupMenu {
selectedTimelined.resetTimeline();
swf.updateCharacters();
mainPanel.refreshTree(swf);
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
}
}
private void addTagBeforeActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) {
@@ -943,7 +1106,7 @@ public class TagTreeContextMenu extends JPopupMenu {
index = calcFramePositionToAdd(frame, timelined, true, new Reference<>(false), false);
}
if (timelined != null) {
if (index == -1) {
timelined.addTag(t);
@@ -963,6 +1126,7 @@ public class TagTreeContextMenu extends JPopupMenu {
swf.updateCharacters();
mainPanel.refreshTree(swf);
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex);
}
@@ -982,7 +1146,7 @@ public class TagTreeContextMenu extends JPopupMenu {
} else if (item instanceof Frame) {
Frame frame = (Frame) item;
timelined = frame.timeline.timelined;
index = calcFramePositionToAdd(frame, timelined, false, new Reference<>(false), false);
} else if (item instanceof HeaderItem) {
timelined = swf;
@@ -1008,6 +1172,7 @@ public class TagTreeContextMenu extends JPopupMenu {
swf.updateCharacters();
mainPanel.refreshTree(swf);
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex);
}
@@ -2205,7 +2370,7 @@ public class TagTreeContextMenu extends JPopupMenu {
allowedInsideSprite = true;
}
SelectTagPositionDialog dialog = new SelectTagPositionDialog(Main.getDefaultDialogsOwner(), t.getSwf(), t, timelined, allowedInsideSprite);
SelectTagPositionDialog dialog = new SelectTagPositionDialog(Main.getDefaultDialogsOwner(), t.getSwf(), t, timelined, allowedInsideSprite, false);
if (dialog.showDialog() == AppDialog.OK_OPTION) {
Tag selectedTag = dialog.getSelectedTag();
Timelined selectedTimelined = dialog.getSelectedTimelined();
@@ -2234,49 +2399,49 @@ public class TagTreeContextMenu extends JPopupMenu {
private int calcFramePositionToAdd(Frame frame, Timelined timelined, boolean before, Reference<Boolean> frameAdd, boolean addingFramesNotTags) {
ReadOnlyTagList tagsList = timelined.getTags();
int positionToAdd = -1;
if (frame == null) {
positionToAdd = tagsList.size();
} else {
if (before && frame.frame == 0) {
positionToAdd = 0;
} else {
int positionToAdd = -1;
if (frame == null) {
positionToAdd = tagsList.size();
} else {
if (before && frame.frame == 0) {
positionToAdd = 0;
} else {
//adding frames before frame 0 => at 0
//adding frames before frame 2 => after second ShowFrameTag
//adding frames after frame 2 => after third ShowFrameTag
//adding frames after frame 0 => after first ShowFrameTag
int f = 0;
int i = 0;
for (; i < tagsList.size(); i++) {
Tag t = tagsList.get(i);
if (t instanceof ShowFrameTag) {
f++;
//adding frames before frame 0 => at 0
//adding frames before frame 2 => after second ShowFrameTag
//adding frames after frame 2 => after third ShowFrameTag
//adding frames after frame 0 => after first ShowFrameTag
int f = 0;
int i = 0;
for (; i < tagsList.size(); i++) {
Tag t = tagsList.get(i);
if (t instanceof ShowFrameTag) {
f++;
if (before && f == frame.frame) {
positionToAdd = i;
if (addingFramesNotTags) {
positionToAdd++;
}
break;
}
if (!before && f == frame.frame + 1) {
positionToAdd = i + 1;
break;
}
if (before && f == frame.frame) {
positionToAdd = i;
if (addingFramesNotTags) {
positionToAdd++;
}
break;
}
if (f == 0 && !before) { //last showFrameTag not found
if (!tagsList.isEmpty()) { //DefineSprite with some tags but no ShowFrameTag
frameAdd.setVal(true);
}
positionToAdd = tagsList.size();
if (!before && f == frame.frame + 1) {
positionToAdd = i + 1;
break;
}
}
}
return positionToAdd;
if (f == 0 && !before) { //last showFrameTag not found
if (!tagsList.isEmpty()) { //DefineSprite with some tags but no ShowFrameTag
frameAdd.setVal(true);
}
positionToAdd = tagsList.size();
}
}
}
return positionToAdd;
}
private void addFrames(boolean before) {
TreeItem item = getTree().getCurrentTreeItem();
if (item == null) {
@@ -2312,7 +2477,7 @@ public class TagTreeContextMenu extends JPopupMenu {
if (frameAdd.getVal()) {
frameCount++;
}
SWF swf = timelined.getTimeline().swf;
for (int i = 0; i < frameCount; i++) {
ShowFrameTag showFrameTag = new ShowFrameTag(swf);