Merge pull request #138 from jindrapetrik/dev

Dev
This commit is contained in:
Jindra Petřík
2022-10-31 19:18:03 +01:00
committed by GitHub
16 changed files with 493 additions and 466 deletions

View File

@@ -1,6 +1,23 @@
# Change Log
All notable changes to this project will be documented in this file.
## [Unreleased]
### 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
- Clone tag menuitem renamed to just Clone as it clones both tags and frames
## [16.0.0] - 2022-10-30
### Added
- Replace characters references

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<>();
@@ -218,27 +220,49 @@ public class SelectTagPositionDialog extends AppDialog {
root.addChild(endNode);
}
private void selectPath(List<Object> 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<Object> path) {
if (selectedTag == null && !allowInsideSprites) {
}
for (int i = 0; i < root.getChildCount(); i++) {
MyTreeNode node = (MyTreeNode) root.getChildAt(i);
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 (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(selectNext ? nextPath : subPath);
return;
}
if (timelined == selectedTimelined && (node.getData() instanceof MyTimelineEnd) && selectedTag == null) {
selectPath(subPath);
return;
}
if ((selectedTimelined instanceof DefineSpriteTag) && !allowInsideSprites && node.getData() == selectedTimelined) {
selectPath(nextPath);
return;
}
if (node.getData() instanceof DefineSpriteTag) {
selectCurrent(node, (DefineSpriteTag) node.getData(), subPath);
@@ -249,13 +273,13 @@ 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 {
private boolean selected;
public PositionTreeCellRenderer() {
if (View.isOceanic()) {
setUI(new BasicLabelUI());
@@ -278,24 +302,25 @@ 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;
}
}
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();
@@ -374,7 +399,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 +420,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;

View File

@@ -60,5 +60,6 @@ public enum TreeNodeType {
METADATA,
PLACE_OBJECT,
REMOVE_OBJECT,
SCALING_GRID,
END
}

View File

@@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -517,15 +517,18 @@ config.description.displayAs3PCodeDocsPanel = Show panel with documentation of i
config.name.displayAs3TraitsListAndConstantsPanel = Show AS3 traits list and constants panel
config.description.displayAs3TraitsListAndConstantsPanel = Show panel with list of traits and constants under the tag tree for AS3
#after 14.1.0
config.name.useAsTypeIcons = Use script icons based on item type
config.description.useAsTypeIcons = Use different icons for different script types (class/interface/frame/...)
config.name.limitAs3PCodeOffsetMatching = Limit of AS3 P-code offset matching
config.description.limitAs3PCodeOffsetMatching = Limit of instructions in AS3 P-code which are offset-matched to AS3 script
#after 14.2.1
config.name.showSlowRenderingWarning = Log warning when rendering is too slow
config.description.showSlowRenderingWarning = Logs warning when internal flash viewer is too slow to display content
#after 14.3.1
config.name.autoCloseQuotes = Auto close single quotes on script edit
config.description.autoCloseQuotes = Automatically inserts second single quote ' on typing first one
@@ -541,9 +544,11 @@ config.description.autoCloseParenthesis = Automatically inserts closing parenthe
config.name.showDialogOnError = Show error dialog on every error
config.description.showDialogOnError = Automatically displays error dialog on every error occurrence
#after 14.4.0
config.name.limitSameChars = Limit of the same characters for \\{xx}C (repeat) escape
config.description.limitSameChars = Maximum number of the same characters in a row in P-code strings or obufuscated names before replacing with \\{xx}C repeat escape
#after 14.5.2
config.name.showImportScriptsInfo = Show information before importing scripts
config.description.showImportScriptsInfo = Displays some info about how importing scripts works after clicking Import scripts in the menu.
@@ -556,6 +561,7 @@ config.description.showImportSymbolClassInfo = Displays some info about how Symb
config.name.showImportXmlInfo = Show information before importing XML
config.description.showImportXmlInfo = Displays some info about how XML importing works after clicking Import XML in the menu.
#after 15.1.1
config.name.lastSessionTagListSelection = Last session tag list selection
config.description.lastSessionTagListSelection = Contains the selection from the last session on the list selection view

View File

@@ -24,4 +24,5 @@ installed = Installed:
ttffile.noselection = TTF file: <select>
ttffile.selection = TTF file: %fontname% (%filename%)
allcharacters = All characters (%available% characters)
#after 14.0.0
ascentdescentleading = Set ascent, descent and leading

View File

@@ -795,6 +795,7 @@ message.confirm.removemultiple.nodep = Are you sure you want to remove %count% i
menu.recentSearches = Recent searches for current file
menu.recentSearches.empty = Recent searches list is empty
#after 14.1.0
menu.tools.otherTools.clearRecentSearches = Clear all recent searches
menu.recentSearches.clear = clear search results
message.confirm.recentSearches.clear = Do you really want to clear recent searches for current file?
@@ -807,8 +808,10 @@ message.character.notfound = Character %characterid% not found.
FileChooser.preview = Preview
FileChooser.previewNotAvailable = (preview not available)
#after 14.2.1
button.freetransform = Free transform
#after 14.3.1
error.outOfMemory.title = Error - out of memory
error.outOfMemory = The decompiler ran out of memory. Current maximum size of Java Heap is set to %maxheap%.
error.outOfMemory.windows = It is set to maximum available when you run app via "ffdec.exe".\nIf you run the app via "ffdec.bat", you can configure it in that file manually to higher value.
@@ -827,6 +830,7 @@ notavailable.activex.disable = You can enable using internal viewer by uncheckin
Advanced Settings / Other / (Deprecated) Use Adobe Flash player for preview of objects\n \
But unfortunately, this won't work for movie tags.
#after 14.5.2
button.showin.flashprojector = Show in flash projector
message.info = Information
@@ -846,8 +850,10 @@ message.info.importSymbolClass = During importing Symbol-Class, you need to sele
message.info.importXml = For XML importing, you need a XML file in special format - the format in which FFDec exports.\r\n \
The best way to create such XML file is to export XML from existing SWF first.
#after 14.6.0
tagInfo.dependentFrames = Dependent Frames
#after 15.0.0
imagePanel.depth = depth:
work.importing_as = Importing script
@@ -857,6 +863,7 @@ work.deobfuscating_pcode = Deobfuscating pcode
work.injecting_debuginfo = Injecting debug info
work.generating_swd = Generating SWD file
#after 15.1.1
button.replaceRefs = Replace references with other character ID
contextmenu.cloneTag = Clone tag
@@ -886,3 +893,8 @@ 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
contextmenu.cloneFrame = Clone frame
contextmenu.clone = Clone

View File

@@ -862,4 +862,9 @@ 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
contextmenu.cloneFrame = Klonovat sn\u00edmek
contextmenu.clone = Klonovat

View File

@@ -30,6 +30,7 @@ checkbox.searchAS = Search in AS
checkbox.replaceInParameters = Replace in parameters
checkbox.searchPCode = Search in P-Code
#after 13.0.3
label.scope = Scope:
scope.currentFile = Current SWF

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,11 +31,22 @@ 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;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
@@ -43,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;
@@ -295,9 +319,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 +495,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);
@@ -494,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();
@@ -605,10 +639,33 @@ 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;
}
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

@@ -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<Integer> getSwfFolderItemNestedTagIds(String folderName, boolean gfx) {
List<Integer> ret = new ArrayList<>();
switch (folderName) {
@@ -479,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

@@ -18,22 +18,15 @@ package com.jpexs.decompiler.flash.gui.tagtree;
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWC;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.ZippedSWFBundle;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
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.configuration.Configuration;
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;
@@ -46,51 +39,39 @@ import com.jpexs.decompiler.flash.gui.ViewMessages;
import com.jpexs.decompiler.flash.gui.abc.AddClassDialog;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
import com.jpexs.decompiler.flash.gui.action.AddScriptDialog;
import com.jpexs.decompiler.flash.iggy.conversion.IggySwfBundle;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
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.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
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.ExportAssetsTag;
import com.jpexs.decompiler.flash.tags.FileAttributesTag;
import com.jpexs.decompiler.flash.tags.FrameLabelTag;
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.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;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.timeline.AS2Package;
import com.jpexs.decompiler.flash.timeline.AS3Package;
import com.jpexs.decompiler.flash.timeline.Frame;
@@ -109,6 +90,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;
@@ -174,14 +156,14 @@ public class TagTreeContextMenu extends JPopupMenu {
private JMenuItem closeMenuItem;
private JMenu addTagMenu;
private JMenu addTagInsideMenu;
private JMenu addTagBeforeMenu;
private JMenu addTagAfterMenu;
private JMenuItem cloneTagMenuItem;
private JMenuItem cloneMenuItem;
private JMenu moveTagToMenu;
private JMenu copyTagMenu;
@@ -227,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"));
@@ -295,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"));
@@ -307,10 +289,10 @@ public class TagTreeContextMenu extends JPopupMenu {
addTagAfterMenu.setIcon(View.getIcon("addtag16"));
add(addTagAfterMenu);
cloneTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.cloneTag"));
cloneTagMenuItem.addActionListener(this::cloneTagActionPerformed);
cloneTagMenuItem.setIcon(View.getIcon("copy16"));
add(cloneTagMenuItem);
cloneMenuItem = new JMenuItem(mainPanel.translate("contextmenu.clone"));
cloneMenuItem.addActionListener(this::cloneActionPerformed);
cloneMenuItem.setIcon(View.getIcon("copy16"));
add(cloneMenuItem);
moveTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.moveTagAround"));
moveTagMenuItem.addActionListener(this::moveTagActionPerformed);
@@ -331,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"));
@@ -586,7 +568,7 @@ public class TagTreeContextMenu extends JPopupMenu {
expandRecursiveMenuItem.setVisible(false);
removeMenuItem.setVisible(canRemove);
removeWithDependenciesMenuItem.setVisible(canRemove && !allDoNotHaveDependencies);
cloneTagMenuItem.setVisible(allSelectedIsTagOrFrame && allSelectedSameParent);
cloneMenuItem.setVisible(allSelectedIsTagOrFrame && allSelectedSameParent);
undoTagMenuItem.setVisible(allSelectedIsTag);
exportSelectionMenuItem.setEnabled(hasExportableNodes); //?
replaceMenuItem.setVisible(false);
@@ -599,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);
@@ -610,8 +592,8 @@ public class TagTreeContextMenu extends JPopupMenu {
addAs3ClassMenuItem.setVisible(false);
textSearchMenuItem.setVisible(hasScripts || hasTexts);
moveTagMenuItem.setVisible(items.size() == 1 && (items.get(0) instanceof Tag));
showInResourcesViewTagMenuItem.setVisible(items.size() == 1 && mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && (!(items.get(0) instanceof ShowFrameTag)));
showInTagListViewTagMenuItem.setVisible(items.size() == 1 && mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES);
showInResourcesViewTagMenuItem.setVisible(false);
showInTagListViewTagMenuItem.setVisible(false);
addFramesMenuItem.setVisible(false);
addFramesBeforeMenuItem.setVisible(false);
addFramesAfterMenuItem.setVisible(false);
@@ -683,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) {
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) {
@@ -727,6 +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) {
@@ -790,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;
@@ -875,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);
@@ -903,14 +1035,44 @@ public class TagTreeContextMenu extends JPopupMenu {
case EndTag.ID:
allowedInsideSprite = true;
}
SWF swf = item.getSwf();
Timelined selectedTimelined = null;
Tag selectedTag = null;
boolean selectNext = false;
if (item instanceof DefineSpriteTag) {
selectedTimelined = (DefineSpriteTag) item;
} else if (item instanceof Frame) {
Frame frame = (Frame) item;
selectedTimelined = frame.timeline.timelined;
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;
}
SWF swf = item.getSwf();
SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), swf, allowedInsideSprite);
SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), swf, selectedTag, selectedTimelined, allowedInsideSprite, selectNext);
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});
//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) {
@@ -938,22 +1101,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) {
@@ -975,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);
}
@@ -992,22 +1144,13 @@ 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;
Frame frame = (Frame) item;
timelined = frame.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;
}
}
}
index = calcFramePositionToAdd(frame, timelined, false, new Reference<>(false), false);
} else if (item instanceof HeaderItem) {
timelined = swf;
index = 0;
}
if (timelined != null) {
@@ -1029,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);
}
@@ -2101,7 +2245,7 @@ public class TagTreeContextMenu extends JPopupMenu {
}
}
private void cloneTagActionPerformed(ActionEvent e) {
private void cloneActionPerformed(ActionEvent e) {
List<TreeItem> items = getTree().getSelected();
/* Currently useless since all selected items must have the same parent
* but a better way to detect for parent/child selection
@@ -2226,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();
@@ -2253,6 +2397,51 @@ public class TagTreeContextMenu extends JPopupMenu {
addFrames(true);
}
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 {
//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) {
@@ -2283,44 +2472,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<Boolean> 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);

View File

@@ -94,7 +94,7 @@ public class TagTreeModel extends AbstractTagTreeModel {
private final Map<SWF, TagTreeSwfInfo> swfInfos = new HashMap<>();
private final boolean addAllFolders;
private final Map<TreeItem, TreePath> pathCache = new HashMap<>();
public TagTreeModel(List<SWFList> swfs, boolean addAllFolders) {
@@ -144,7 +144,7 @@ public class TagTreeModel extends AbstractTagTreeModel {
swfInfos.clear();
TreePath changedPath = getTreePath(swf == null ? root : swf);
fireTreeStructureChanged(new TreeModelEvent(this, changedPath));
}
}
private List<SoundStreamHeadTypeTag> getSoundStreams(DefineSpriteTag sprite) {
List<SoundStreamHeadTypeTag> ret = new ArrayList<>();
@@ -408,7 +408,7 @@ public class TagTreeModel extends AbstractTagTreeModel {
}
return ret;
}
@Override
public TreeItem getRoot() {
return root;
@@ -452,8 +452,12 @@ public class TagTreeModel extends AbstractTagTreeModel {
@Override
public List<? extends TreeItem> getAllChildren(Object parent) {
TreeItem parentNode = (TreeItem) parent;
List<TreeItem> result = new ArrayList<>();
if (parentNode instanceof CharacterTag) {
result = new ArrayList<>(getMappedCharacters(((CharacterTag) parentNode).getSwf(), (CharacterTag) parentNode));
}
if (parentNode == root) {
List<TreeItem> result = new ArrayList<>(swfs.size());
for (SWFList swfList : swfs) {
if (!swfList.isBundle()) {
result.add(swfList.get(0));
@@ -470,11 +474,11 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else if (parentNode instanceof Frame) {
return ((Frame) parentNode).innerTags;
} else if (parentNode instanceof DefineSpriteTag) {
return ((DefineSpriteTag) parentNode).getTimeline().getFrames();
result.addAll(((DefineSpriteTag) parentNode).getTimeline().getFrames());
return result;
} else if (parentNode instanceof DefineBinaryDataTag) {
DefineBinaryDataTag binaryDataTag = (DefineBinaryDataTag) parentNode;
if (binaryDataTag.innerSwf != null) {
List<SWF> result = new ArrayList<>(1);
result.add(((DefineBinaryDataTag) parentNode).innerSwf);
return result;
} else {
@@ -484,7 +488,6 @@ public class TagTreeModel extends AbstractTagTreeModel {
return ((AS2Package) parentNode).getAllChildren();
} else if (parentNode instanceof FrameScript) {
Frame parentFrame = ((FrameScript) parentNode).getFrame();
List<TreeItem> result = new ArrayList<>();
result.addAll(parentFrame.actionContainers);
result.addAll(parentFrame.actions);
for (int i = 0; i < result.size(); i++) {
@@ -518,16 +521,14 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else {
return new ArrayList<>();
}
} else if (parentNode instanceof CharacterTag) {
return getMappedCharacters(((CharacterTag) parentNode).getSwf(), (CharacterTag) parentNode);
}
return new ArrayList<>();
return result;
}
@Override
public TreeItem getChild(Object parent, int index) {
if(getChildCount(parent) == 0) {
if (getChildCount(parent) == 0) {
return null;
}
TreeItem parentNode = (TreeItem) parent;
@@ -643,7 +644,7 @@ public class TagTreeModel extends AbstractTagTreeModel {
@Override
public boolean isLeaf(Object node) {
return (getChildCount(node) == 0);
}
}
private int indexOfAdd(int prevSize, int index) {
if (index == -1) {
@@ -707,5 +708,5 @@ public class TagTreeModel extends AbstractTagTreeModel {
}
return -1;
}
}
}