diff --git a/CHANGELOG.md b/CHANGELOG.md index a62074a67..989c77d5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java index 4918bd5cc..d6f1edf07 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java @@ -307,7 +307,7 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable { return knownTagInfosByName; } - + private static void addTagInfo(Map map, Map map2, int id, Class cls, String name) { map.put(id, new TagTypeInfo(id, cls, name)); map2.put(name, new TagTypeInfo(id, cls, name)); diff --git a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java index a27ccb11c..50a6fd046 100644 --- a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java @@ -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 children = new ArrayList<>(); @@ -242,9 +244,14 @@ public class SelectTagPositionDialog extends AppDialog { List subPath = new ArrayList<>(path); subPath.add(node); + + List 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(); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 49bf3cea5..ca96e19fc 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -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 \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 3d7f8527b..dd4cb5e13 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -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. \ No newline at end of file +form\u00e1t souboru nen\u00ed zn\u00e1m. + +#after 16.0.0 +contextmenu.addTagInside = P\u0159idat tag dovnit\u0159 \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java index 82b19174f..14efad03e 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java @@ -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 getNestedTagIds(Tag obj) { - if (obj instanceof DefineSpriteTag) { - return getSpriteNestedTagIds(); - } - return new ArrayList<>(); - } - - private List 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 getFrameNestedTagIds(boolean inSprite) { - if (inSprite) { - return getSpriteNestedTagIds(); - } - return null; //null = all possible tags - } } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java index 3d3bf8c4c..97b92cb2b 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java @@ -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 getNestedTagIds(Tag obj); - public abstract List getFrameNestedTagIds(boolean inSprite); + public static List 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 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<>(); + } } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java index fdaba6c33..ccf43b3bb 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java @@ -295,41 +295,7 @@ public class TagTree extends AbstractTagTree { return ret; } - - @Override - public List 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 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 getSelection(SWF swf) { List sel; diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 3f1426f94..61efe6c3b 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -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 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 allowedTagTypes = TagTree.getSwfFolderItemNestedTagIds(folder, gfx); - if (allowedTagTypes.isEmpty()) { + Map classes = Tag.getKnownClasses(); + + List allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(folder, gfx)); + Set 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(mappedTagTypes), folderMenu, item, listener); + addTagMenu.add(folderMenu); } + + private void addAddTagInsideMenuItems(TreeItem item) + { + AddTagActionListener listener = this::addTagInsideActionPerformed; + Map 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 allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem)item).getName(), gfx)); + + Set 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(mappedTagTypes), addTagInsideMenu, item, listener); + return; + } - private void addAddTagMenuItems(List allowedTagTypes, JMenu addTagMenu, TreeItem item, AddTagActionLisener listener) { + if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES) { + List 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 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 allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem)parent).getName(), gfx)); + + Set 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(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 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 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);