diff --git a/CHANGELOG.md b/CHANGELOG.md index 81ae2f667..dde75e0ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ All notable changes to this project will be documented in this file. - Drag and drop to move/copy tags in the tag list view - Setting for enabling placing Define tags into DefineSprite - Icons for tags in replace character dialog +- Move tag with dependencies +- Copy/Move tag operation has select position dialog +- Select position dialog has target file in its title + +### Fixed +- Exception when bundle selected +- File path in window title for SWFs inside DefineBinaryData ## [16.2.0] - 2022-11-08 ### Added diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index c7e66cdb4..4fd1feefa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -1438,6 +1438,38 @@ public final class SWF implements SWFContainerItem, Timelined { } return new File(title).getName(); } + + /** + * Gets title of this SWF incuding parent nodes like SwfList and DefineBinaryData + * @return + */ + public String getShortPathTitle() { + if (binaryData != null) { + return binaryData.getSwf().getShortPathTitle()+ "/DefineBinaryData (" + binaryData.getCharacterId() + ")"; + } + if (swfList != null) { + if (swfList.isBundle()) { + return swfList.name + "/" + getShortFileName(); + } + } + return getShortFileName(); + } + + /** + * Gets full path title of this SWF incuding parent nodes like SwfList and DefineBinaryData + * @return + */ + public String getFullPathTitle() { + if (binaryData != null) { + return binaryData.getSwf().getFullPathTitle()+ "/DefineBinaryData (" + binaryData.getCharacterId() + ")"; + } + if (swfList != null) { + if (swfList.isBundle()) { + return swfList.sourceInfo.getFileTitleOrName() + "/" + getFileTitle(); + } + } + return getFileTitle(); + } public void setFile(String file) { this.file = file; @@ -3920,5 +3952,15 @@ public final class SWF implements SWFContainerItem, Timelined { public void setFileTitle(String fileTitle) { this.fileTitle = fileTitle; - } + } + + @Override + public int getFrameCount() { + return frameCount; + } + + @Override + public void setFrameCount(int frameCount) { + this.frameCount = frameCount; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index 60a70cade..181575416 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -297,4 +297,14 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer { timeline.addFrame(frameHit); } + + @Override + public int getFrameCount() { + return 4; + } + + @Override + public void setFrameCount(int frameCount) { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 4ce1af159..27a855238 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -288,4 +288,14 @@ public class DefineButtonTag extends ButtonTag implements ASMSourceContainer { timeline.addFrame(frameHit); } + + @Override + public int getFrameCount() { + return 4; + } + + @Override + public void setFrameCount(int frameCount) { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 7ae843c11..f26ce377c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -464,4 +464,14 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { } return ret; } + + @Override + public int getFrameCount() { + return frameCount; + } + + @Override + public void setFrameCount(int frameCount) { + this.frameCount = frameCount; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timelined.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timelined.java index 162e58b1e..6b368b6ee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timelined.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timelined.java @@ -47,4 +47,8 @@ public interface Timelined extends BoundedTag { public void replaceTag(Tag oldTag, Tag newTag); public int indexOfTag(Tag tag); + + public void setFrameCount(int frameCount); + + public int getFrameCount(); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index c0191805f..396f9780c 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -28,6 +28,7 @@ import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; import com.jpexs.decompiler.flash.gui.helpers.CheckResources; import com.jpexs.decompiler.flash.search.ScriptSearchResult; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.treeitems.SWFList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Helper; @@ -746,6 +747,10 @@ public abstract class MainFrameMenu implements MenuBuilder { List items = mainPanel.getCurrentTree().getSelected(); SWF firstSwf = null; for (TreeItem item : items) { + if (item instanceof SWFList) { + allSameSwf = false; + break; + } if (firstSwf == null) { firstSwf = item.getSwf(); } else { @@ -830,10 +835,7 @@ public abstract class MainFrameMenu implements MenuBuilder { if (Configuration.displayFileName.get() && swf != null) { titleBuilder.append(" - "); - if (swf.swfList != null && swf.swfList.isBundle()) { - titleBuilder.append(swf.swfList.name).append("/"); - } - titleBuilder.append(swf.getFileTitle()); + titleBuilder.append(swf.getFullPathTitle()); } mainFrame.setTitle(titleBuilder.toString()); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index f42b23d72..44a635588 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -4786,6 +4786,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se public RECT getRectWithStrokes() { return getRect(); } + + @Override + public void setFrameCount(int frameCount) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public int getFrameCount() { + return getTimeline().getFrameCount(); + } }; } diff --git a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java index 0a6846cd5..677aca0b8 100644 --- a/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SelectTagPositionDialog.java @@ -321,7 +321,7 @@ public class SelectTagPositionDialog extends AppDialog { this.selectedTimelined = selectedTimelined; this.allowInsideSprites = allowInsideSprites; this.selectNext = selectNext; - setTitle(translate("dialog.title")); + setTitle(translate("dialog.title").replace("%filetitle%", swf.getShortPathTitle())); setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); Container cnt = getContentPane(); cnt.setLayout(new BorderLayout()); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 5d997e893..eb749348e 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -942,4 +942,7 @@ import.image.result = %count% images imported. clipboard.hint = Number of items in the tag clipboard clipboard.item = 1 item clipboard.items = %count% items -clipboard.clear = Clear the tag clipboard \ No newline at end of file +clipboard.clear = Clear the tag clipboard + +#after 16.2.0 +contextmenu.moveTagWithDependencies = Move tag with dependencies to \ 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 17c17d4cb..cfcf0589d 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -914,4 +914,7 @@ import.image.result = %count% obr\u00e1zk\u016f importov\u00e1no. clipboard.hint = Po\u010det polo\u017eek v tagov\u00e9 schr\u00e1nce clipboard.item = 1 polo\u017eka clipboard.items = %count% polo\u017eek -clipboard.clear = Vy\u010distit tagovou schr\u00e1nku \ No newline at end of file +clipboard.clear = Vy\u010distit tagovou schr\u00e1nku + +#after 16.2.0 +contextmenu.moveTagWithDependencies = P\u0159esunout tag se z\u00e1vislostmi do \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog.properties index d515cda56..f9a13cc00 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog.properties @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -dialog.title = Select tag position +dialog.title = Select tag position in %filetitle% button.ok = OK button.cancel = Cancel timeline.end = end of timeline \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog_cs.properties index 5abf3785d..b7c98d2f7 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/SelectTagPositionDialog_cs.properties @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -dialog.title = Vyberte pozici tagu +dialog.title = Vyberte pozici tagu v %filetitle% button.ok = OK button.cancel = Storno timeline.end = konec timeliny \ 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 706d4dd99..a0643dc0a 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java @@ -239,7 +239,7 @@ class TreeTransferHandler extends TransferHandler { } } } - mainPanel.getContextPopupMenu().copyOrMoveTagsBeforeAfter(sourceItems, (action & MOVE) == MOVE, timelined, position); + mainPanel.getContextPopupMenu().copyOrMoveTags(sourceItems, (action & MOVE) == MOVE, timelined, position); } @Override diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 1f82e0622..9bf7bf0bf 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -168,6 +168,8 @@ public class TagTreeContextMenu extends JPopupMenu { private JMenu moveTagToMenu; + private JMenu moveTagToWithDependenciesMenu; + private JMenu copyTagToMenu; private JMenu copyTagToWithDependenciesMenu; @@ -205,8 +207,9 @@ public class TagTreeContextMenu extends JPopupMenu { private JMenuItem addFramesAfterMenuItem; private static final int KIND_MOVETO = 0; - private static final int KIND_COPYTO = 1; - private static final int KIND_COPYTODEPS = 2; + private static final int KIND_MOVETODEPS = 1; + private static final int KIND_COPYTO = 2; + private static final int KIND_COPYTODEPS = 3; public TagTreeContextMenu(final List trees, MainPanel mainPanel) { this.mainPanel = mainPanel; @@ -350,6 +353,11 @@ public class TagTreeContextMenu extends JPopupMenu { moveTagToMenu.setIcon(View.getIcon("move16")); add(moveTagToMenu); + moveTagToWithDependenciesMenu = new JMenu(mainPanel.translate("contextmenu.moveTagWithDependencies")); + moveTagToWithDependenciesMenu.setIcon(View.getIcon("move16")); + add(moveTagToWithDependenciesMenu); + + copyTagToMenu = new JMenu(mainPanel.translate("contextmenu.copyTag")); copyTagToMenu.setIcon(View.getIcon("copy16")); add(copyTagToMenu); @@ -664,6 +672,7 @@ public class TagTreeContextMenu extends JPopupMenu { addTagBeforeMenu.setVisible(false); addTagAfterMenu.setVisible(false); moveTagToMenu.setVisible(false); + moveTagToWithDependenciesMenu.setVisible(false); copyTagToMenu.setVisible(false); copyTagToWithDependenciesMenu.setVisible(false); cutTagToClipboardMenuItem.setVisible(false); @@ -848,6 +857,7 @@ public class TagTreeContextMenu extends JPopupMenu { } moveTagToMenu.removeAll(); + moveTagToWithDependenciesMenu.removeAll(); copyTagToMenu.removeAll(); copyTagToWithDependenciesMenu.removeAll(); @@ -892,10 +902,12 @@ public class TagTreeContextMenu extends JPopupMenu { continue; } addCopyMoveToMenusSwfList(KIND_MOVETO, singleSwf, targetSwfList, moveTagToMenu, items); + addCopyMoveToMenusSwfList(KIND_MOVETODEPS, singleSwf, targetSwfList, moveTagToWithDependenciesMenu, items); addCopyMoveToMenusSwfList(KIND_COPYTO, singleSwf, targetSwfList, copyTagToMenu, items); addCopyMoveToMenusSwfList(KIND_COPYTODEPS, singleSwf, targetSwfList, copyTagToWithDependenciesMenu, items); } moveTagToMenu.setVisible(true); + moveTagToWithDependenciesMenu.setVisible(true); copyTagToMenu.setVisible(true); copyTagToWithDependenciesMenu.setVisible(true); } @@ -1198,11 +1210,7 @@ public class TagTreeContextMenu extends JPopupMenu { t.setTimelined(timelined); timelined.resetTimeline(); - if (timelined instanceof SWF) { - ((SWF) timelined).frameCount = timelined.getTimeline().getFrameCount(); - } else if (timelined instanceof DefineSpriteTag) { - ((DefineSpriteTag) timelined).frameCount = timelined.getTimeline().getFrameCount(); - } + timelined.setFrameCount(timelined.getTimeline().getFrameCount()); } swf.updateCharacters(); @@ -1244,11 +1252,7 @@ public class TagTreeContextMenu extends JPopupMenu { t.setTimelined(timelined); timelined.resetTimeline(); - if (timelined instanceof SWF) { - ((SWF) timelined).frameCount = timelined.getTimeline().getFrameCount(); - } else if (timelined instanceof DefineSpriteTag) { - ((DefineSpriteTag) timelined).frameCount = timelined.getTimeline().getFrameCount(); - } + timelined.setFrameCount(timelined.getTimeline().getFrameCount()); } swf.updateCharacters(); @@ -1278,22 +1282,26 @@ public class TagTreeContextMenu extends JPopupMenu { } private void moveTagToActionPerformed(ActionEvent evt, List items, SWF targetSwf) { - ReadOnlyTagList tags = targetSwf.getTags();; - boolean lastIsShowFrame = !tags.isEmpty() && (tags.get(tags.size() - 1) instanceof ShowFrameTag); + SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), targetSwf, true); + if (selectPositionDialog.showDialog() != AppDialog.OK_OPTION) { + return; + } + Tag position = selectPositionDialog.getSelectedTag(); + Timelined timelined = selectPositionDialog.getSelectedTimelined(); + ReadOnlyTagList tags = timelined.getTags();; SWF sourceSwf = items.get(0).getSwf(); for (TreeItem item : items) { Tag tag = (Tag) item; - sourceSwf.removeTag(tag); + timelined.removeTag(tag); tag.setSwf(targetSwf, true); + tag.setTimelined(timelined); checkUniqueCharacterId(tag); - targetSwf.addTag(tag); + int positionInt = position == null ? timelined.getTags().size() : timelined.indexOfTag(position); + timelined.addTag(positionInt, tag); targetSwf.updateCharacters(); tag.setModified(true); } - if (lastIsShowFrame) { - targetSwf.frameCount++; - } sourceSwf.assignExportNamesToSymbols(); targetSwf.assignExportNamesToSymbols(); sourceSwf.assignClassesToSymbols(); @@ -1304,121 +1312,42 @@ public class TagTreeContextMenu extends JPopupMenu { targetSwf.updateCharacters(); sourceSwf.resetTimelines(sourceSwf); targetSwf.resetTimelines(targetSwf); + + timelined.setFrameCount(timelined.getTimeline().getFrameCount()); + mainPanel.refreshTree(new SWF[]{sourceSwf, targetSwf}); } private void copyTagToActionPerformed(ActionEvent evt, List items, SWF targetSwf) { - try { - ReadOnlyTagList tags = targetSwf.getTags();; - boolean lastIsShowFrame = !tags.isEmpty() && (tags.get(tags.size() - 1) instanceof ShowFrameTag); - for (TreeItem item : items) { - Tag tag = (Tag) item; - Tag copyTag = tag.cloneTag(); - copyTag.setSwf(targetSwf, true); - copyTag.setTimelined(targetSwf); - checkUniqueCharacterId(copyTag); - targetSwf.addTag(copyTag); - targetSwf.updateCharacters(); - copyTag.setModified(true); - } - - if (lastIsShowFrame) { - targetSwf.frameCount++; - } - - targetSwf.resetTimelines(targetSwf); - - targetSwf.assignExportNamesToSymbols(); - targetSwf.assignClassesToSymbols(); - targetSwf.clearImageCache(); - targetSwf.updateCharacters(); - mainPanel.refreshTree(targetSwf); - } catch (IOException | InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); + SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), targetSwf, true); + if (selectPositionDialog.showDialog() != AppDialog.OK_OPTION) { + return; } + Tag position = selectPositionDialog.getSelectedTag(); + Timelined timelined = selectPositionDialog.getSelectedTimelined(); + copyOrMoveTags(new LinkedHashSet(items), false, timelined, position); } - private void copyTagWithDependenciesToActionPerformed(ActionEvent evt, List items, SWF targetSwf) { - try { - ReadOnlyTagList tags = targetSwf.getTags();; - boolean lastIsShowFrame = !tags.isEmpty() && (tags.get(tags.size() - 1) instanceof ShowFrameTag); - SWF sourceSwf = items.get(0).getSwf(); - for (TreeItem item : items) { - Set copiedTags = new HashSet<>(); - Set newTags = new HashSet<>(); - Set needed = new LinkedHashSet<>(); - Map changedCharacterIds = new HashMap<>(); - - Tag tag = (Tag) item; - tag.getNeededCharactersDeep(needed); - Tag copyTag; - - List neededList = new ArrayList<>(); - for (Integer characterId : needed) { - neededList.add(characterId); - } - - // first add dependencies in reverse order - for (int i = neededList.size() - 1; i >= 0; i--) { - int characterId = neededList.get(i); - CharacterTag neededTag = sourceSwf.getCharacter(characterId); - if (!copiedTags.contains(neededTag)) { - copyTag = neededTag.cloneTag(); - copyTag.setSwf(targetSwf, true); - copyTag.setTimelined(targetSwf); - int oldCharacterId = neededTag.getCharacterId(); - int newCharacterId = checkUniqueCharacterId(copyTag); - changedCharacterIds.put(oldCharacterId, newCharacterId); - - targetSwf.addTag(copyTag); - - targetSwf.updateCharacters(); - targetSwf.getCharacters(); // force rebuild character id cache - copyTag.setModified(true); - copiedTags.add(neededTag); - newTags.add(copyTag); - } - } - - copyTag = tag.cloneTag(); - copyTag.setSwf(targetSwf, true); - copyTag.setTimelined(targetSwf); - if (tag instanceof CharacterTag) { - CharacterTag characterTag = (CharacterTag) copyTag; - int oldCharacterId = characterTag.getCharacterId(); - int newCharacterId = checkUniqueCharacterId(copyTag); - changedCharacterIds.put(oldCharacterId, newCharacterId); - } - targetSwf.addTag(copyTag); - - targetSwf.updateCharacters(); - targetSwf.getCharacters(); // force rebuild character id cache - copyTag.setModified(true); - copiedTags.add(tag); - newTags.add(copyTag); - - for (int oldCharacterId : changedCharacterIds.keySet()) { - int newCharacterId = changedCharacterIds.get(oldCharacterId); - for (Tag newTag : newTags) { - // todo: avoid double replaces - newTag.replaceCharacter(oldCharacterId, newCharacterId); - } - } - } - - if (lastIsShowFrame) { - targetSwf.frameCount++; - } - - targetSwf.assignExportNamesToSymbols(); - targetSwf.assignClassesToSymbols(); - targetSwf.clearImageCache(); - targetSwf.updateCharacters(); - targetSwf.resetTimelines(targetSwf); - mainPanel.refreshTree(targetSwf); - } catch (IOException | InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); + private void copyTagWithDependenciesToActionPerformed(ActionEvent evt, List items, SWF targetSwf) { + SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), targetSwf, true); + if (selectPositionDialog.showDialog() != AppDialog.OK_OPTION) { + return; } + Tag position = selectPositionDialog.getSelectedTag(); + Timelined timelined = selectPositionDialog.getSelectedTimelined(); + + copyOrMoveTags(getDependenciesSet(items), false, timelined, position); + } + + private void moveTagWithDependenciesToActionPerformed(ActionEvent evt, List items, SWF targetSwf) { + SelectTagPositionDialog selectPositionDialog = new SelectTagPositionDialog(mainPanel.getMainFrame().getWindow(), targetSwf, true); + if (selectPositionDialog.showDialog() != AppDialog.OK_OPTION) { + return; + } + Tag position = selectPositionDialog.getSelectedTag(); + Timelined timelined = selectPositionDialog.getSelectedTimelined(); + + copyOrMoveTags(getDependenciesSet(items), true, timelined, position); } private void openSwfInsideActionPerformed(ActionEvent evt) { @@ -2627,6 +2556,9 @@ public class TagTreeContextMenu extends JPopupMenu { case KIND_MOVETO: moveTagToActionPerformed(ae, items, targetSwf); break; + case KIND_MOVETODEPS: + moveTagWithDependenciesToActionPerformed(ae, items, targetSwf); + break; case KIND_COPYTO: copyTagToActionPerformed(ae, items, targetSwf); break; @@ -2684,9 +2616,9 @@ public class TagTreeContextMenu extends JPopupMenu { mainPanel.copyToClipboard(items); } - private Set getClipboardDependenciesSet(List items) { + private Set getDependenciesSet(List items) { SWF sourceSwf = items.get(0).getSwf(); - Set clipboardItems = new LinkedHashSet<>(); + Set newItems = new LinkedHashSet<>(); for (TreeItem item : items) { Set needed = new LinkedHashSet<>(); Tag tag = (Tag) item; @@ -2700,17 +2632,17 @@ public class TagTreeContextMenu extends JPopupMenu { for (int n = neededList.size() - 1; n >= 0; n--) { int characterId = neededList.get(n); CharacterTag neededTag = sourceSwf.getCharacter(characterId); - if (!clipboardItems.contains(neededTag)) { - clipboardItems.add(neededTag); + if (!newItems.contains(neededTag)) { + newItems.add(neededTag); } } - clipboardItems.add(item); + newItems.add(item); } - return clipboardItems; + return newItems; } public void copyTagToClipboardWithDependenciesActionPerformed(ActionEvent evt, List items) { - mainPanel.copyToClipboard(getClipboardDependenciesSet(items)); + mainPanel.copyToClipboard(getDependenciesSet(items)); } public void cutTagToClipboardActionPerformed(ActionEvent evt) { @@ -2721,7 +2653,7 @@ public class TagTreeContextMenu extends JPopupMenu { public void cutTagToClipboardWithDependenciesActionPerformed(ActionEvent evt) { List items = getTree().getSelected(); - mainPanel.cutToClipboard(getClipboardDependenciesSet(items)); + mainPanel.cutToClipboard(getDependenciesSet(items)); mainPanel.repaintTree(); } @@ -2740,7 +2672,7 @@ public class TagTreeContextMenu extends JPopupMenu { } ReadOnlyTagList tags = timelined.getTags(); position = positionInt < tags.size() ? tags.get(positionInt) : null; - copyOrMoveTagsBeforeAfter(mainPanel.getClipboardContents(), mainPanel.isClipboardCut(), timelined, position); + copyOrMoveTags(mainPanel.getClipboardContents(), mainPanel.isClipboardCut(), timelined, position); if (mainPanel.isClipboardCut()) { mainPanel.emptyClipboard(); @@ -2762,7 +2694,7 @@ public class TagTreeContextMenu extends JPopupMenu { } ReadOnlyTagList tags = timelined.getTags(); position = positionInt < tags.size() ? tags.get(positionInt) : null; - copyOrMoveTagsBeforeAfter(mainPanel.getClipboardContents(), mainPanel.isClipboardCut(), timelined, position); + copyOrMoveTags(mainPanel.getClipboardContents(), mainPanel.isClipboardCut(), timelined, position); if (mainPanel.isClipboardCut()) { mainPanel.emptyClipboard(); @@ -2781,14 +2713,14 @@ public class TagTreeContextMenu extends JPopupMenu { timelined = (Timelined) item; position = null; } - copyOrMoveTagsBeforeAfter(mainPanel.getClipboardContents(), mainPanel.isClipboardCut(), timelined, position); + copyOrMoveTags(mainPanel.getClipboardContents(), mainPanel.isClipboardCut(), timelined, position); if (mainPanel.isClipboardCut()) { mainPanel.emptyClipboard(); } } - public void copyOrMoveTagsBeforeAfter(Set items, boolean move, Timelined targetTimelined, Tag position) { + public void copyOrMoveTags(Set items, boolean move, Timelined targetTimelined, Tag position) { Set sourceSwfs = new LinkedHashSet<>(); SWF targetSwf = (targetTimelined instanceof SWF) ? (SWF) targetTimelined : ((DefineSpriteTag) targetTimelined).getSwf(); try {