diff --git a/CHANGELOG.md b/CHANGELOG.md index 578e11cd2..a62074a67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,13 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ### Added - Allow add tag after header context menu +- DefineScalingGrid has icon ### 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 ## [16.0.0] - 2022-10-30 ### Added diff --git a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java index 2a0d38755..a27ccb11c 100644 --- a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java @@ -218,27 +218,44 @@ public class SelectTagPositionDialog extends AppDialog { root.addChild(endNode); } + private void selectPath(List path) { + Object[] pathArray = path.toArray(new Object[path.size()]); + TreePath tpath = new TreePath(pathArray); + positionTree.setSelectionPath(tpath); + int row = positionTree.getRowForPath(tpath); + if (row != -1) { + Rectangle rect = positionTree.getRowBounds(row); + rect.width += rect.x; + rect.x = 0; + positionTree.scrollRectToVisible(rect); + } + } + private void selectCurrent(MyTreeNode root, Timelined timelined, List path) { + if (selectedTag == null && !allowInsideSprites) { + + } + for (int i = 0; i < root.getChildCount(); i++) { MyTreeNode node = (MyTreeNode) root.getChildAt(i); List subPath = new ArrayList<>(path); subPath.add(node); - if (node.getData() == selectedTag && timelined == selectedTimelined) { - Object[] pathArray = subPath.toArray(new Object[subPath.size()]); - TreePath tpath = new TreePath(pathArray); - positionTree.setSelectionPath(tpath); - int row = positionTree.getRowForPath(tpath); - if (row != -1) { - Rectangle rect = positionTree.getRowBounds(row); - rect.width += rect.x; - rect.x = 0; - positionTree.scrollRectToVisible(rect); - } + if (timelined == selectedTimelined && ((node.getData() == selectedTag))) { + selectPath(subPath); return; } + if (timelined == selectedTimelined && (node.getData() instanceof MyTimelineEnd) && selectedTag == null) { + selectPath(subPath); + return; + } + if ((selectedTimelined instanceof DefineSpriteTag) && !allowInsideSprites && node.getData() == selectedTimelined) { + selectPath(subPath); + return; + } + if (node.getData() instanceof DefineSpriteTag) { selectCurrent(node, (DefineSpriteTag) node.getData(), subPath); @@ -255,7 +272,7 @@ public class SelectTagPositionDialog extends AppDialog { private static class PositionTreeCellRenderer extends DefaultTreeCellRenderer { private boolean selected; - + public PositionTreeCellRenderer() { if (View.isOceanic()) { setUI(new BasicLabelUI()); @@ -278,12 +295,12 @@ public class SelectTagPositionDialog extends AppDialog { if (subValue instanceof MyTimelineEnd) { lab.setIcon(TagTree.getIconForType(TreeNodeType.END)); } - + if (subValue instanceof MyFrame) { lab.setIcon(TagTree.getIconForType(TreeNodeType.FRAME)); } if (subValue instanceof TreeItem) { - lab.setIcon(TagTree.getIconForType(TagTree.getTreeNodeType((TreeItem)subValue))); + lab.setIcon(TagTree.getIconForType(TagTree.getTreeNodeType((TreeItem) subValue))); } } return renderer; @@ -374,7 +391,7 @@ public class SelectTagPositionDialog extends AppDialog { positionTree.addTreeSelectionListener(this::spriteValueChanged); positionTree.addTreeSelectionListener(this::positionTreeValueChanged); positionTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - + previewPanel = new PreviewPanel(Main.getMainFrame().getPanel(), null); previewPanel.setReadOnly(true); previewPanel.setPreferredSize(new Dimension(300, 1)); @@ -395,14 +412,14 @@ public class SelectTagPositionDialog extends AppDialog { setResizable(true); View.centerScreen(this); View.setWindowIcon(this); - + calculateEnabled(); } public void positionTreeValueChanged(TreeSelectionEvent e) { calculateEnabled(); } - + private void calculateEnabled() { MyTreeNode node = (MyTreeNode) positionTree.getLastSelectedPathComponent(); boolean enabled = true; diff --git a/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java b/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java index 5ab7e7837..a65bab14a 100644 --- a/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java +++ b/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java @@ -60,5 +60,6 @@ public enum TreeNodeType { METADATA, PLACE_OBJECT, REMOVE_OBJECT, + SCALING_GRID, END } diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java index f80693244..a9903e130 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java @@ -49,6 +49,7 @@ import com.jpexs.decompiler.flash.tags.DefineFont4Tag; import com.jpexs.decompiler.flash.tags.DefineFontTag; import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag; import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag; +import com.jpexs.decompiler.flash.tags.DefineScalingGridTag; import com.jpexs.decompiler.flash.tags.DefineShape2Tag; import com.jpexs.decompiler.flash.tags.DefineShape3Tag; import com.jpexs.decompiler.flash.tags.DefineShape4Tag; @@ -218,6 +219,9 @@ public class DumpTree extends JTree { case RemoveObject2Tag.NAME: nodeType = TreeNodeType.REMOVE_OBJECT; break; + case DefineScalingGridTag.NAME: + nodeType = TreeNodeType.SCALING_GRID; + break; default: nodeType = TreeNodeType.OTHER_TAG; } diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/scalinggrid16.png b/src/com/jpexs/decompiler/flash/gui/graphics/scalinggrid16.png new file mode 100644 index 000000000..736d879d4 Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/scalinggrid16.png differ diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java index ad990aeef..3d3bf8c4c 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java @@ -36,6 +36,7 @@ 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.DefineFontTag; +import com.jpexs.decompiler.flash.tags.DefineScalingGridTag; import com.jpexs.decompiler.flash.tags.DefineSoundTag; import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; @@ -295,9 +296,13 @@ public abstract class AbstractTagTree extends JTree { return TreeNodeType.REMOVE_OBJECT; } + if (t instanceof DefineScalingGridTag) { + return TreeNodeType.SCALING_GRID; + } + if (t instanceof EndTag) { return TreeNodeType.END; - } + } if (t instanceof Tag) { return TreeNodeType.OTHER_TAG; @@ -467,7 +472,8 @@ public abstract class AbstractTagTree extends JTree { } if (nodeType == TreeNodeType.FONT) { ret.add(d); - } + } + if (nodeType == TreeNodeType.OTHER_TAG) { if (d instanceof SymbolClassTypeTag) { ret.add(d); @@ -605,9 +611,13 @@ public abstract class AbstractTagTree extends JTree { return TreeNodeType.END; } + if (cl == DefineScalingGridTag.class) { + return TreeNodeType.SCALING_GRID; + } + if (Tag.class.isAssignableFrom(cl)) { return TreeNodeType.OTHER_TAG; - } + } return TreeNodeType.FOLDER; } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java index 963a4e2b8..fdaba6c33 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java @@ -233,191 +233,7 @@ public class TagTree extends AbstractTagTree { super(treeModel, mainPanel); setCellRenderer(new TagTreeCellRenderer()); } - - public static TreeNodeType getTreeNodeType(TreeItem t) { - - if (t instanceof TagScript) { - t = ((TagScript) t).getTag(); - } - - if (t instanceof HeaderItem) { - return TreeNodeType.HEADER; - } - - if ((t instanceof DefineFontTag) - || (t instanceof DefineFont2Tag) - || (t instanceof DefineFont3Tag) - || (t instanceof DefineFont4Tag) - || (t instanceof DefineCompactedFont)) { - return TreeNodeType.FONT; - } - - // DefineText, DefineText2, DefineEditTextTag - if (t instanceof TextTag) { - return TreeNodeType.TEXT; - } - - // DefineBits, DefineBitsJPEG2, DefineBitsJPEG3, DefineBitsJPEG4, DefineBitsLossless, DefineBitsLossless2 - if (t instanceof ImageTag) { - return TreeNodeType.IMAGE; - } - - // DefineShape, DefineShape2, DefineShape3, DefineShape4 - if (t instanceof ShapeTag) { - return TreeNodeType.SHAPE; - } - - // DefineMorphShape, DefineMorphShape2 - if (t instanceof MorphShapeTag) { - return TreeNodeType.MORPH_SHAPE; - } - - if (t instanceof DefineSpriteTag) { - return TreeNodeType.SPRITE; - } - - // DefineButton, DefineButton2 - if (t instanceof ButtonTag) { - return TreeNodeType.BUTTON; - } - - if (t instanceof DefineVideoStreamTag) { - return TreeNodeType.MOVIE; - } - - if ((t instanceof DefineSoundTag) || (t instanceof SoundStreamHeadTag) || (t instanceof SoundStreamHead2Tag)) { - return TreeNodeType.SOUND; - } - - if (t instanceof DefineBinaryDataTag) { - return TreeNodeType.BINARY_DATA; - } - - if (Configuration.useAsTypeIcons.get()) { - if (t instanceof DoInitActionTag) { - DoInitActionTag doInit = (DoInitActionTag) t; - if (doInit.getSwf().getExportName(doInit.spriteId) != null) { - return TreeNodeType.AS_CLASS; - } - return TreeNodeType.AS_INIT; - } - - if (t instanceof CLIPACTIONRECORD) { - return TreeNodeType.AS_CLIP; - } - - if (t instanceof BUTTONCONDACTION) { - return TreeNodeType.AS_BUTTON; - } - - if (t instanceof DoActionTag) { - return TreeNodeType.AS_FRAME; - } - } - - if (t instanceof ASMSource) { - return TreeNodeType.AS; - } - - if (t instanceof ScriptPack) { - if (Configuration.useAsTypeIcons.get()) { - ScriptPack pack = (ScriptPack) t; - Trait trait = pack.getPublicTrait(); - if (trait == null) { - return TreeNodeType.AS; - } - if (trait instanceof TraitFunction) { - return TreeNodeType.AS_FUNCTION; - } - if (trait instanceof TraitMethodGetterSetter) { - return TreeNodeType.AS_FUNCTION; - } - if (trait instanceof TraitSlotConst) { - TraitSlotConst traitSlotConst = (TraitSlotConst) trait; - if (traitSlotConst.isConst()) { - return TreeNodeType.AS_CONST; - } else { - return TreeNodeType.AS_VAR; - } - } - if (trait instanceof TraitClass) { - TraitClass traitClass = (TraitClass) trait; - if (pack.abc.instance_info.get(traitClass.class_info).isInterface()) { - return TreeNodeType.AS_INTERFACE; - } - return TreeNodeType.AS_CLASS; - } - } - return TreeNodeType.AS; - } - - if (t instanceof AS2Package) { - return TreeNodeType.PACKAGE; - } - - if (t instanceof AS3Package) { - return TreeNodeType.PACKAGE; - } - - if ((t instanceof Frame) - || (t instanceof FrameScript)) { - return TreeNodeType.FRAME; - } - - if (t instanceof ShowFrameTag) { - return TreeNodeType.SHOW_FRAME; - } - - if (t instanceof SWF) { - return TreeNodeType.FLASH; - } - - if (t instanceof SWFList) { - SWFList slist = (SWFList) t; - if (slist.isBundle()) { - if (slist.bundle.getClass() == ZippedSWFBundle.class) { - return TreeNodeType.BUNDLE_ZIP; - } else if (slist.bundle.getClass() == SWC.class) { - return TreeNodeType.BUNDLE_SWC; - } else if (slist.bundle.getClass() == IggySwfBundle.class) { - return TreeNodeType.BUNDLE_IGGY; - } else { - return TreeNodeType.BUNDLE_BINARY; - } - } - } - - if (t instanceof SetBackgroundColorTag) { - return TreeNodeType.SET_BACKGROUNDCOLOR; - } - if (t instanceof FileAttributesTag) { - return TreeNodeType.FILE_ATTRIBUTES; - } - if (t instanceof MetadataTag) { - return TreeNodeType.METADATA; - } - if (t instanceof PlaceObjectTypeTag) { - return TreeNodeType.PLACE_OBJECT; - } - if (t instanceof RemoveTag) { - return TreeNodeType.REMOVE_OBJECT; - } - - if (t instanceof EndTag) { - return TreeNodeType.END; - } - - if (t instanceof Tag) { - return TreeNodeType.OTHER_TAG; - } - - if (t instanceof FolderItem) { - return TreeNodeType.FOLDER; - } - - return TreeNodeType.FOLDER; - } - + public static List getSwfFolderItemNestedTagIds(String folderName, boolean gfx) { List ret = new ArrayList<>(); switch (folderName) { diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index ee573f489..3f1426f94 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -88,6 +88,7 @@ import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Reference; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -891,11 +892,23 @@ public class TagTreeContextMenu extends JPopupMenu { allowedInsideSprite = true; } - SWF swf = item.getSwf(); - SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), swf, allowedInsideSprite); + SWF swf = item.getSwf(); + Timelined selectedTimelined = null; + Tag selectedTag = null; + if (item instanceof DefineSpriteTag) { + selectedTimelined = (DefineSpriteTag) item; + } + if (item instanceof Frame) { + Frame frame = (Frame) item; + selectedTimelined = frame.timeline.timelined; + if (!frame.allInnerTags.isEmpty()){ + selectedTag = frame.allInnerTags.get(frame.allInnerTags.size() - 1); + } + } + SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), swf, selectedTag, selectedTimelined, allowedInsideSprite); if (selectPositionDialog.showDialog() == AppDialog.OK_OPTION) { - Timelined selectedTimelined = selectPositionDialog.getSelectedTimelined(); - Tag selectedTag = selectPositionDialog.getSelectedTag(); + selectedTimelined = selectPositionDialog.getSelectedTimelined(); + selectedTag = selectPositionDialog.getSelectedTag(); try { Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); t.setTimelined(selectedTimelined); @@ -925,22 +938,10 @@ public class TagTreeContextMenu extends JPopupMenu { timelined = itemTag.getTimelined(); index = timelined.indexOfTag(itemTag); } else if (item instanceof Frame) { - Frame f = (Frame) item; - timelined = f.timeline.timelined; + Frame frame = (Frame) item; + timelined = frame.timeline.timelined; - if (!f.innerTags.isEmpty()) { - index = timelined.indexOfTag(f.innerTags.get(0)); - } else if (f.showFrameTag != null) { - index = timelined.indexOfTag(f.showFrameTag); - } else { - ReadOnlyTagList inner = timelined.getTags(); - for (int i = inner.size() - 1; i > 0; i--) { - if (inner.get(i) instanceof ShowFrameTag) { - index = i + 1; - break; - } - } - } + index = calcFramePositionToAdd(frame, timelined, true, new Reference<>(false), false); } if (timelined != null) { @@ -979,22 +980,10 @@ public class TagTreeContextMenu extends JPopupMenu { timelined = itemTag.getTimelined(); index = timelined.indexOfTag(itemTag) + 1; } else if (item instanceof Frame) { - Frame f = (Frame) item; - timelined = f.timeline.timelined; - - if (f.showFrameTag != null) { - index = timelined.indexOfTag(f.showFrameTag) + 1; - } else if (!f.innerTags.isEmpty()) { - index = timelined.indexOfTag(f.innerTags.get(f.innerTags.size() - 1)) + 1; - } else { - ReadOnlyTagList inner = timelined.getTags(); - for (int i = inner.size() - 1; i > 0; i--) { - if (inner.get(i) instanceof ShowFrameTag) { - index = i + 1; - break; - } - } - } + Frame frame = (Frame) item; + timelined = frame.timeline.timelined; + + index = calcFramePositionToAdd(frame, timelined, false, new Reference<>(false), false); } else if (item instanceof HeaderItem) { timelined = swf; index = 0; @@ -2243,6 +2232,51 @@ public class TagTreeContextMenu extends JPopupMenu { addFrames(true); } + 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 { + + //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 (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) { @@ -2273,44 +2307,12 @@ public class TagTreeContextMenu extends JPopupMenu { if (frameCount == 0) { return; } - ReadOnlyTagList tagsList = timelined.getTags(); - 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++; - - if (before && f == frame.frame) { - positionToAdd = i + 1; - break; - } - if (!before && f == frame.frame + 1) { - positionToAdd = i + 1; - break; - } - } - } - if (f == 0 && !before) { //last showFrameTag not found - if (!tagsList.isEmpty()) { //DefineSprite with some tags but no ShowFrameTag - frameCount++; - } - positionToAdd = tagsList.size(); - } - } + Reference frameAdd = new Reference<>(false); + int positionToAdd = calcFramePositionToAdd(frame, timelined, before, frameAdd, true); + if (frameAdd.getVal()) { + frameCount++; } + SWF swf = timelined.getTimeline().swf; for (int i = 0; i < frameCount; i++) { ShowFrameTag showFrameTag = new ShowFrameTag(swf);