Added Context menu items to create new tags (shape, sprite, image, movie, sound, binaryData) from files and using font embed dialog for fonts

This commit is contained in:
Jindra Petřík
2023-11-05 21:11:10 +01:00
parent f3341c5490
commit 9d4a8feb2b
17 changed files with 359 additions and 66 deletions
+2
View File
@@ -11,6 +11,8 @@ All notable changes to this project will be documented in this file.
- ActionScript Debugger - Call stack frames switching - view variables around call stack - ActionScript Debugger - Call stack frames switching - view variables around call stack
- ActionScript Debugger - Highlight lines of callstack - ActionScript Debugger - Highlight lines of callstack
- [#2105] GFX - Basic tag info - [#2105] GFX - Basic tag info
- Context menu items to create new tags (shape, sprite, image, movie, sound, binaryData) from files
and using font embed dialog for fonts
### Fixed ### Fixed
- [#1306], [#1768] Maximizing window on other than main monitor - [#1306], [#1768] Maximizing window on other than main monitor
@@ -53,8 +53,16 @@ public class ImageImporter extends TagImporter {
return importImage(it, newData, 0); return importImage(it, newData, 0);
} }
/**
*
* @param it
* @param newData
* @param tagType 0 = can change for defineBits, -1 = detect based on data
* @return
* @throws IOException
*/
public Tag importImage(ImageTag it, byte[] newData, int tagType) throws IOException { public Tag importImage(ImageTag it, byte[] newData, int tagType) throws IOException {
if (newData[0] == 'B' && newData[1] == 'M') { if (newData.length >= 2 && newData[0] == 'B' && newData[1] == 'M') {
BufferedImage b = ImageHelper.read(newData); BufferedImage b = ImageHelper.read(newData);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageHelper.write(b, ImageFormat.PNG, baos); ImageHelper.write(b, ImageFormat.PNG, baos);
@@ -69,6 +77,18 @@ public class ImageImporter extends TagImporter {
tagType = it.getId(); tagType = it.getId();
} }
} }
if (tagType == -1) {
if (newData.length >= 4
&& newData[0] == (byte) 0xff
&& newData[1] == (byte) 0xd8
&& newData[2] == (byte) 0xff
&& newData[3] == (byte) 0xe0
) {
tagType = DefineBitsJPEG2Tag.ID;
} else {
tagType = DefineBitsLosslessTag.ID;
}
}
if (it.getId() == tagType) { if (it.getId() == tagType) {
it.setImage(newData); it.setImage(newData);
@@ -108,6 +128,7 @@ public class ImageImporter extends TagImporter {
imageTag.setModified(true); imageTag.setModified(true);
it.getTimelined().replaceTag(it, imageTag); it.getTimelined().replaceTag(it, imageTag);
imageTag.setTimelined(it.getTimelined());
swf.updateCharacters(); swf.updateCharacters();
swf.resetTimelines(swf); swf.resetTimelines(swf);
return imageTag; return imageTag;
@@ -261,9 +261,13 @@ public class MovieImporter {
if (timelined != null) { if (timelined != null) {
timelined.resetTimeline(); timelined.resetTimeline();
} }
if (timelined == null) {
timelined = movie.getTimelined();
}
int startFrame = 0; int startFrame = 0;
int placeDepth = -1; int placeDepth = -1;
int maxPlaceDepth = 0;
if (timelined != null) { if (timelined != null) {
for (Tag t : timelined.getTags()) { for (Tag t : timelined.getTags()) {
if (t instanceof ShowFrameTag) { if (t instanceof ShowFrameTag) {
@@ -275,13 +279,47 @@ public class MovieImporter {
placeDepth = pt.getDepth(); placeDepth = pt.getDepth();
break; break;
} }
if (pt.getDepth() > -1) {
if (pt.getDepth() > maxPlaceDepth) {
maxPlaceDepth = pt.getDepth();
}
}
} }
} }
} }
if (placeDepth == -1) {
placeDepth = maxPlaceDepth + 1;
startFrame = 0;
}
int numTimelineFrames = timelined == null ? 0 : timelined.getFrameCount(); int numTimelineFrames = timelined == null ? 0 : timelined.getFrameCount();
int importLastFrame = -1; int importLastFrame = -1;
if (timelined != null) { if (timelined != null) {
boolean placeWithCharacterIdFound = false;
ReadOnlyTagList tagList1 = timelined.getTags();
for (int p = 0; p < tagList1.size(); p++) {
Tag t = tagList1.get(p);
if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag place = (PlaceObjectTypeTag) t;
if (place.getCharacterId() == movie.characterID) {
placeWithCharacterIdFound = true;
}
}
if (t instanceof ShowFrameTag) {
if (!placeWithCharacterIdFound) {
PlaceObject2Tag placeObject = new PlaceObject2Tag(swf);
placeObject.setTimelined(timelined);
placeObject.placeFlagHasCharacter = true;
placeObject.characterId = movie.characterID;
placeObject.depth = placeDepth;
placeObject.placeFlagMove = false;
timelined.addTag(p, placeObject);
break;
}
}
}
VideoFrameTag lastVideoFrame = null; VideoFrameTag lastVideoFrame = null;
for (FLVTAG ftag : videoTags) { for (FLVTAG ftag : videoTags) {
videoData = ((VIDEODATA) ftag.data); videoData = ((VIDEODATA) ftag.data);
@@ -322,10 +360,28 @@ public class MovieImporter {
ReadOnlyTagList tagList = timelined.getTags(); ReadOnlyTagList tagList = timelined.getTags();
int p = 0; int p = 0;
boolean found = false; boolean found = false;
boolean placeFound = false;
for (; p < tagList.size(); p++) { for (; p < tagList.size(); p++) {
Tag t = tagList.get(p); Tag t = tagList.get(p);
if (t instanceof ShowFrameTag) { if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag place = (PlaceObjectTypeTag) t;
if (place.getDepth() == placeDepth) {
placeFound = true;
}
}
if (t instanceof ShowFrameTag) {
swfFrameNum++; swfFrameNum++;
if (!placeFound) {
PlaceObject2Tag placeObject = new PlaceObject2Tag(swf);
placeObject.setTimelined(timelined);
placeObject.depth = placeDepth;
placeObject.placeFlagMove = true;
placeObject.placeFlagHasRatio = true;
placeObject.ratio = swfFrameNum - startFrame;
timelined.addTag(p, placeObject);
p++;
}
placeFound = false;
if (swfFrameNum == idealFrame) { if (swfFrameNum == idealFrame) {
found = true; found = true;
break; break;
@@ -81,13 +81,33 @@ public class FontEmbedDialog extends AppDialog {
private final JCheckBox allCheckbox; private final JCheckBox allCheckbox;
private final JCheckBox importAscentDescentLeadingCheckBox; private final JCheckBox importAscentDescentLeadingCheckBox;
private final JTextField fontNameTextField;
public String getCreateFontName() {
return fontNameTextField.getText();
}
public Font getSelectedFont() { public Font getSelectedFont() {
if (ttfFileRadio.isSelected() && customFont != null) { if (ttfFileRadio.isSelected() && customFont != null) {
return customFont; return customFont;
} }
return ((FontFace) faceSelection.getSelectedItem()).font; return ((FontFace) faceSelection.getSelectedItem()).font;
} }
public boolean isBold() {
if (ttfFileRadio.isSelected() && customFont != null) {
return customFont.isBold();
}
return ((FontFace) faceSelection.getSelectedItem()).isBold();
}
public boolean isItalic() {
if (ttfFileRadio.isSelected() && customFont != null) {
return customFont.isItalic();
}
return ((FontFace) faceSelection.getSelectedItem()).isItalic();
}
public boolean isImportAscentDescentLeading() { public boolean isImportAscentDescentLeading() {
return importAscentDescentLeadingCheckBox.isSelected(); return importAscentDescentLeadingCheckBox.isSelected();
@@ -134,15 +154,27 @@ public class FontEmbedDialog extends AppDialog {
faceSelection.setModel(FontPanel.getFaceModel((FontFamily) familyNamesSelection.getSelectedItem())); faceSelection.setModel(FontPanel.getFaceModel((FontFamily) familyNamesSelection.getSelectedItem()));
} }
public FontEmbedDialog(Window owner, boolean hasLayout, FontFace selectedFace, String selectedChars) { public FontEmbedDialog(Window owner, boolean hasLayout, FontFace selectedFace, String selectedChars, boolean create) {
super(owner); super(owner);
setSize(900, 600); setSize(900, 600);
setDefaultCloseOperation(HIDE_ON_CLOSE); setDefaultCloseOperation(HIDE_ON_CLOSE);
setTitle(translate("dialog.title")); setTitle(translate("dialog.title"));
Container cnt = getContentPane(); Container cnt = getContentPane();
cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS)); cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS));
fontNameTextField = new JTextField(30);
fontNameTextField.setText(translate("font.name.default"));
fontNameTextField.selectAll();
if (create) {
JPanel fontNamePanel = new JPanel(new FlowLayout());
fontNamePanel.add(new JLabel(translate("font.name")));
fontNamePanel.add(fontNameTextField);
cnt.add(fontNamePanel);
}
JPanel selFontPanel = new JPanel(new FlowLayout()); JPanel selFontPanel = new JPanel(new FlowLayout());
installedRadio = new JRadioButton(translate("installed")); installedRadio = new JRadioButton(translate("installed"));
@@ -163,6 +195,7 @@ public class FontEmbedDialog extends AppDialog {
JButton loadFromDiskButton = new JButton(View.getIcon("open16")); JButton loadFromDiskButton = new JButton(View.getIcon("open16"));
loadFromDiskButton.setToolTipText(translate("button.loadfont")); loadFromDiskButton.setToolTipText(translate("button.loadfont"));
loadFromDiskButton.addActionListener(this::loadFromDiscButtonActionPerformed); loadFromDiskButton.addActionListener(this::loadFromDiscButtonActionPerformed);
selFontPanel.add(new JLabel(translate("font.source")));
selFontPanel.add(installedRadio); selFontPanel.add(installedRadio);
selFontPanel.add(familyNamesSelection); selFontPanel.add(familyNamesSelection);
selFontPanel.add(faceSelection); selFontPanel.add(faceSelection);
@@ -257,9 +290,12 @@ public class FontEmbedDialog extends AppDialog {
importAscentDescentLeadingCheckBox = new JCheckBox(translate("ascentdescentleading")); importAscentDescentLeadingCheckBox = new JCheckBox(translate("ascentdescentleading"));
importAscentDescentLeadingCheckBox.setAlignmentX(Component.CENTER_ALIGNMENT); importAscentDescentLeadingCheckBox.setAlignmentX(Component.CENTER_ALIGNMENT);
if (hasLayout) { if (hasLayout && !create) {
cnt.add(importAscentDescentLeadingCheckBox); cnt.add(importAscentDescentLeadingCheckBox);
} }
if (create) {
importAscentDescentLeadingCheckBox.setSelected(true);
}
JPanel buttonsPanel = new JPanel(new FlowLayout()); JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton okButton = new JButton(AppStrings.translate("button.ok")); JButton okButton = new JButton(AppStrings.translate("button.ok"));
@@ -44,6 +44,14 @@ public class FontFace implements Comparable<FontFace> {
return face; return face;
} }
public boolean isBold() {
return toString().toLowerCase().contains("bold");
}
public boolean isItalic() {
return toString().toLowerCase().contains("italic");
}
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;
@@ -615,37 +615,51 @@ public class FontPanel extends JPanel implements TagEditorPanel {
} }
} }
} }
public boolean fontEmbed(TreeItem item, boolean create) {
if (item == null) {
return false;
}
FontTag ft = (FontTag) item;
FontEmbedDialog fed = new FontEmbedDialog(Main.getDefaultDialogsOwner(), ft.hasLayout() || ft.getCharacterCount() == 0, (FontFace) fontFaceSelection.getSelectedItem(), fontAddCharactersField.getText(), create);
if (fed.showDialog() == AppDialog.OK_OPTION) {
Set<Integer> selChars = fed.getSelectedChars();
if (!selChars.isEmpty() || fed.isImportAscentDescentLeading()) {
if (ft.getCharacterCount() == 0) {
ft.setHasLayout(true);
}
Font selFont = fed.getSelectedFont();
fontFamilyNameSelection.setSelectedItem(new FontFamily(selFont));
fontFaceSelection.setSelectedItem(new FontFace(selFont));
fontAddChars(ft, selChars, selFont);
if (fed.isImportAscentDescentLeading()) {
Font adlFont = selFont;
if (selFont.getSize() != 1024) {
adlFont = selFont.deriveFont(1024f);
}
ft.setAscent((int) (ft.getDivider() * this.getFontMetrics(adlFont).getAscent()));
ft.setDescent((int) (ft.getDivider() * this.getFontMetrics(adlFont).getDescent()));
int leading = this.getFontMetrics(adlFont).getAscent() + this.getFontMetrics(adlFont).getDescent() - 1024;
ft.setLeading((int) (ft.getDivider() * leading));
}
if (create) {
ft.setFontNameIntag(fed.getCreateFontName());
ft.setBold(fed.isBold());
ft.setItalic(fed.isItalic());
}
fontAddCharactersField.setText("");
ft.setModified(true);
mainPanel.reload(true);
return true;
}
}
return false;
}
private void fontEmbedButtonActionPerformed(ActionEvent evt) { private void fontEmbedButtonActionPerformed(ActionEvent evt) {
TreeItem item = mainPanel.getCurrentTree().getCurrentTreeItem(); TreeItem item = mainPanel.getCurrentTree().getCurrentTreeItem();
if (item instanceof FontTag) { if (item instanceof FontTag) {
FontTag ft = (FontTag) item; fontEmbed(item, false);
FontEmbedDialog fed = new FontEmbedDialog(Main.getDefaultDialogsOwner(), ft.hasLayout() || ft.getCharacterCount() == 0, (FontFace) fontFaceSelection.getSelectedItem(), fontAddCharactersField.getText());
if (fed.showDialog() == AppDialog.OK_OPTION) {
Set<Integer> selChars = fed.getSelectedChars();
if (!selChars.isEmpty() || fed.isImportAscentDescentLeading()) {
if (ft.getCharacterCount() == 0) {
ft.setHasLayout(true);
}
Font selFont = fed.getSelectedFont();
fontFamilyNameSelection.setSelectedItem(new FontFamily(selFont));
fontFaceSelection.setSelectedItem(new FontFace(selFont));
fontAddChars(ft, selChars, selFont);
if (fed.isImportAscentDescentLeading()) {
Font adlFont = selFont;
if (selFont.getSize() != 1024) {
adlFont = selFont.deriveFont(1024f);
}
ft.setAscent((int) (ft.getDivider() * this.getFontMetrics(adlFont).getAscent()));
ft.setDescent((int) (ft.getDivider() * this.getFontMetrics(adlFont).getDescent()));
int leading = this.getFontMetrics(adlFont).getAscent() + this.getFontMetrics(adlFont).getDescent() - 1024;
ft.setLeading((int) (ft.getDivider() * leading));
}
fontAddCharactersField.setText("");
ft.setModified(true);
mainPanel.reload(true);
}
}
} }
} }
@@ -4422,8 +4422,12 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
} }
public void replaceButtonActionPerformed(List<TreeItem> items) { public void replaceButtonActionPerformed(List<TreeItem> items) {
if (items.size() == 0) { replace(items, false);
return; }
public boolean replace(List<TreeItem> items, boolean create) {
if (items.isEmpty()) {
return false;
} }
TreeItem ti0 = items.get(0); TreeItem ti0 = items.get(0);
@@ -4446,12 +4450,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
if (ti0 instanceof UnknownTag) { if (ti0 instanceof UnknownTag) {
file = showImportFileChooser("", false); file = showImportFileChooser("", false);
} }
for (TreeItem ti : items) { if (file == null) {
doReplaceAction(ti, file); return false;
} }
for (TreeItem ti : items) {
doReplaceAction(ti, file, create);
}
return true;
} }
private void doReplaceAction(TreeItem item, File selectedFile) { private void doReplaceAction(TreeItem item, File selectedFile, boolean create) {
if (selectedFile == null) { if (selectedFile == null) {
return; return;
} }
@@ -4496,7 +4504,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
File selfile = Helper.fixDialogFile(selectedFile); File selfile = Helper.fixDialogFile(selectedFile);
byte[] data = Helper.readFile(selfile.getAbsolutePath()); byte[] data = Helper.readFile(selfile.getAbsolutePath());
try { try {
Tag newTag = new ImageImporter().importImage(it, data); Tag newTag = new ImageImporter().importImage(it, data, create ? -1 : 0);
SWF swf = it.getSwf(); SWF swf = it.getSwf();
if (newTag != null) { if (newTag != null) {
refreshTree(swf); refreshTree(swf);
@@ -4572,9 +4580,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
} }
} }
public void replaceSpriteWithGifButtonActionPerformed(TreeItem item) { public boolean replaceSpriteWithGif(TreeItem item) {
if (item == null) { if (item == null) {
return; return false;
} }
if (item instanceof DefineSpriteTag) { if (item instanceof DefineSpriteTag) {
String filter = "filter.images|*.gif"; String filter = "filter.images|*.gif";
@@ -4595,13 +4603,23 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
} }
reload(true); reload(true);
refreshTree(swf); refreshTree(swf);
return true;
} }
} }
return false;
}
public void replaceSpriteWithGifButtonActionPerformed(TreeItem item) {
replaceSpriteWithGif(item);
} }
public void replaceNoFillButtonActionPerformed(TreeItem item) { public void replaceNoFillButtonActionPerformed(TreeItem item) {
replaceNoFill(item);
}
public boolean replaceNoFill(TreeItem item) {
if (item == null) { if (item == null) {
return; return false;
} }
if (item instanceof ShapeTag) { if (item instanceof ShapeTag) {
@@ -4633,8 +4651,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
ViewMessages.showMessageDialog(this, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); ViewMessages.showMessageDialog(this, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE);
} }
reload(true); reload(true);
return true;
} }
} }
return false;
} }
private void showSvgImportWarning() { private void showSvgImportWarning() {
@@ -6250,4 +6270,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
} }
return dialog; return dialog;
} }
public boolean fontEmbed(TreeItem item, boolean create) {
return previewPanel.getFontPanel().fontEmbed(item, create);
}
} }
@@ -317,8 +317,8 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
if (readOnly) { if (readOnly) {
parametersPanel.setVisible(false); parametersPanel.setVisible(false);
} }
} }
public PreviewPanel(MainPanel mainPanel, FlashPlayerPanel flashPanel) { public PreviewPanel(MainPanel mainPanel, FlashPlayerPanel flashPanel) {
super(JSplitPane.HORIZONTAL_SPLIT, Configuration.guiPreviewSplitPaneDividerLocationPercent); super(JSplitPane.HORIZONTAL_SPLIT, Configuration.guiPreviewSplitPaneDividerLocationPercent);
this.mainPanel = mainPanel; this.mainPanel = mainPanel;
@@ -351,6 +351,10 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
return ret; return ret;
} }
public FontPanel getFontPanel() {
return fontPanel;
}
private void createParametersPanel() { private void createParametersPanel() {
displayWithPreview = new JPanel(new CardLayout()); displayWithPreview = new JPanel(new CardLayout());
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

@@ -26,3 +26,8 @@ ttffile.selection = TTF file: %fontname% (%filename%)
allcharacters = All characters (%available% characters) allcharacters = All characters (%available% characters)
#after 14.0.0 #after 14.0.0
ascentdescentleading = Set ascent, descent and leading ascentdescentleading = Set ascent, descent and leading
#after 19.1.2
font.name = Font name:
font.name.default = My font
font.source = Source:
@@ -25,3 +25,8 @@ ttffile.noselection = TTF soubor: <vyberte>
ttffile.selection = TTF soubor: %fontname% (%filename%) ttffile.selection = TTF soubor: %fontname% (%filename%)
allcharacters = V\u0161echny znaky (%available% znak\u016f) allcharacters = V\u0161echny znaky (%available% znak\u016f)
ascentdescentleading = Nastavit ascent, descent a leading ascentdescentleading = Nastavit ascent, descent a leading
#after 19.1.2
font.name = N\u00e1zev fontu:
font.name.default = Muj font
font.source = Zdroj:
@@ -1195,4 +1195,12 @@ tagInfo.textureFormat = Texture format
tagInfo.padPixels = Pad pixels tagInfo.padPixels = Pad pixels
tagInfo.nominalGlyphSz = Nominal glyph size tagInfo.nominalGlyphSz = Nominal glyph size
tagInfo.glyphCount = Glyph count tagInfo.glyphCount = Glyph count
tagInfo.fontCount = Font count tagInfo.fontCount = Font count
tag.shape.create = create shape from file...
tag.image.create = create image from file...
tag.sprite.create = create sprite from GIF file...
tag.movie.create = create movie from file...
tag.sound.create = create sound from file...
tag.font.create = create font using dialog...
tag.binaryData.create = create binary data from file...
@@ -1172,4 +1172,12 @@ tagInfo.textureFormat = Form\u00e1t textury
tagInfo.padPixels = Zarovn\u00e1n\u00ed pixel\u016f tagInfo.padPixels = Zarovn\u00e1n\u00ed pixel\u016f
tagInfo.nominalGlyphSz = Nomin\u00e1ln\u00ed velikost glyfu tagInfo.nominalGlyphSz = Nomin\u00e1ln\u00ed velikost glyfu
tagInfo.glyphCount = Po\u010det glyf\u016f tagInfo.glyphCount = Po\u010det glyf\u016f
tagInfo.fontCount = Po\u010det p\u00edsem tagInfo.fontCount = Po\u010det p\u00edsem
tag.shape.create = vytvo\u0159it tvar ze souboru...
tag.image.create = vytvo\u0159it obr\u00e1zek ze souboru...
tag.sprite.create = vytvo\u0159it sprite z GIF souboru...
tag.movie.create = vytvo\u0159it video ze souboru...
tag.sound.create = vytvo\u0159it zvuk ze souboru...
tag.font.create = vytvo\u0159it p\u00edsmo pomoc\u00ed dialogu...
tag.binaryData.create = vytvo\u0159it bin\u00e1rn\u00ed data ze souboru...
@@ -47,7 +47,11 @@ import com.jpexs.decompiler.flash.gui.action.AddScriptDialog;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag; import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineFont3Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.DoABC2Tag; import com.jpexs.decompiler.flash.tags.DoABC2Tag;
@@ -1396,8 +1400,7 @@ public class TagTreeContextMenu extends JPopupMenu {
} }
private interface AddTagActionListener { private interface AddTagActionListener {
void call(ActionEvent evt, TreeItem item, Class<?> cl, TreeNodeType createNodeType);
void call(ActionEvent evt, TreeItem item, Class<?> cl);
} }
private void addAddTagMenuFolder(JMenu addTagMenu, String folder, boolean gfx, TreeItem item, AddTagActionListener listener) { private void addAddTagMenuFolder(JMenu addTagMenu, String folder, boolean gfx, TreeItem item, AddTagActionListener listener) {
@@ -1415,11 +1418,11 @@ public class TagTreeContextMenu extends JPopupMenu {
if (allowedTagTypes.isEmpty() && mappedTagTypes.isEmpty()) { if (allowedTagTypes.isEmpty() && mappedTagTypes.isEmpty()) {
return; return;
} }
addAddTagMenuItems(allowedTagTypes, folderMenu, item, listener); addAddTagMenuItems(allowedTagTypes, folderMenu, item, listener, folder);
if (!allowedTagTypes.isEmpty() && !mappedTagTypes.isEmpty()) { if (!allowedTagTypes.isEmpty() && !mappedTagTypes.isEmpty()) {
folderMenu.addSeparator(); folderMenu.addSeparator();
} }
addAddTagMenuItems(new ArrayList<Integer>(mappedTagTypes), folderMenu, item, listener); addAddTagMenuItems(new ArrayList<Integer>(mappedTagTypes), folderMenu, item, listener, null);
addTagMenu.add(folderMenu); addTagMenu.add(folderMenu);
} }
@@ -1427,7 +1430,7 @@ public class TagTreeContextMenu extends JPopupMenu {
private void addAttachTagMenuItems(TreeItem item) { private void addAttachTagMenuItems(TreeItem item) {
AddTagActionListener listener = this::attachTagActionPerformed; AddTagActionListener listener = this::attachTagActionPerformed;
List<Integer> mapped = AbstractTagTree.getMappedTagIdsForClass(item.getClass()); List<Integer> mapped = AbstractTagTree.getMappedTagIdsForClass(item.getClass());
addAddTagMenuItems(mapped, attachTagMenu, item, listener); addAddTagMenuItems(mapped, attachTagMenu, item, listener, null);
} }
private void addAddTagInsideMenuItems(TreeItem item) { private void addAddTagInsideMenuItems(TreeItem item) {
@@ -1440,12 +1443,12 @@ public class TagTreeContextMenu extends JPopupMenu {
boolean gfx = currentSwf.gfx; boolean gfx = currentSwf.gfx;
if (item instanceof SWF) { if (item instanceof SWF) {
addAddTagMenuItems(null, addTagInsideMenu, item, listener); addAddTagMenuItems(null, addTagInsideMenu, item, listener, null);
return; return;
} }
if (item instanceof DefineSpriteTag) { if (item instanceof DefineSpriteTag) {
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener); addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener, TagTreeModel.FOLDER_FRAMES);
addTagInsideMenu.addSeparator(); addTagInsideMenu.addSeparator();
addTagInsideMenu.add(createOthersMenu(item, listener)); addTagInsideMenu.add(createOthersMenu(item, listener));
return; return;
@@ -1455,10 +1458,10 @@ public class TagTreeContextMenu extends JPopupMenu {
Frame frame = (Frame) item; Frame frame = (Frame) item;
boolean insideSprite = frame.timeline.timelined instanceof DefineSpriteTag; boolean insideSprite = frame.timeline.timelined instanceof DefineSpriteTag;
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST) { if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST) {
addAddTagMenuItems(null, addTagInsideMenu, item, listener); addAddTagMenuItems(null, addTagInsideMenu, item, listener, TagTreeModel.FOLDER_FRAMES);
return; return;
} else { } else {
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener); addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagInsideMenu, item, listener, TagTreeModel.FOLDER_FRAMES);
addTagInsideMenu.addSeparator(); addTagInsideMenu.addSeparator();
addTagInsideMenu.add(createOthersMenu(item, listener)); addTagInsideMenu.add(createOthersMenu(item, listener));
} }
@@ -1467,7 +1470,7 @@ public class TagTreeContextMenu extends JPopupMenu {
if (item instanceof FolderItem) { if (item instanceof FolderItem) {
List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem) item).getName(), gfx)); List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem) item).getName(), gfx));
addAddTagMenuItems(allowedTagTypes, addTagInsideMenu, item, listener); addAddTagMenuItems(allowedTagTypes, addTagInsideMenu, item, listener, ((FolderItem) item).getName());
return; return;
} }
@@ -1513,11 +1516,11 @@ public class TagTreeContextMenu extends JPopupMenu {
if (insideFrame) { if (insideFrame) {
if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && !insideSprite) { if (mainPanel.getCurrentView() == MainPanel.VIEW_TAGLIST && !insideSprite) {
addAddTagMenuItems(null, addTagMenu, item, listener); addAddTagMenuItems(null, addTagMenu, item, listener, TagTreeModel.FOLDER_FRAMES);
return; return;
} }
addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagMenu, item, listener); addAddTagMenuItems(AbstractTagTree.getFrameNestedTagIds(), addTagMenu, item, listener, TagTreeModel.FOLDER_FRAMES);
addTagMenu.addSeparator(); addTagMenu.addSeparator();
addTagMenu.add(createOthersMenu(item, listener)); addTagMenu.add(createOthersMenu(item, listener));
@@ -1527,25 +1530,25 @@ public class TagTreeContextMenu extends JPopupMenu {
if (parent instanceof FolderItem) { if (parent instanceof FolderItem) {
List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem) parent).getName(), gfx)); List<Integer> allowedTagTypes = new ArrayList<>(TagTree.getSwfFolderItemNestedTagIds(((FolderItem) parent).getName(), gfx));
addAddTagMenuItems(allowedTagTypes, addTagMenu, item, listener); addAddTagMenuItems(allowedTagTypes, addTagMenu, item, listener, ((FolderItem) parent).getName());
addTagMenu.addSeparator(); addTagMenu.addSeparator();
addTagMenu.add(createOthersMenu(item, listener)); addTagMenu.add(createOthersMenu(item, listener));
return; return;
} }
if ((item instanceof HeaderItem) && !before) { if ((item instanceof HeaderItem) && !before) {
addAddTagMenuItems(null, addTagMenu, item, listener); addAddTagMenuItems(null, addTagMenu, item, listener, null);
} }
} }
private JMenu createOthersMenu(TreeItem item, AddTagActionListener listener) { private JMenu createOthersMenu(TreeItem item, AddTagActionListener listener) {
JMenu othersMenu = new JMenu(AppStrings.translate("node.others")); JMenu othersMenu = new JMenu(AppStrings.translate("node.others"));
othersMenu.setIcon(View.getIcon("folder16")); othersMenu.setIcon(View.getIcon("folder16"));
addAddTagMenuItems(null, othersMenu, item, listener); addAddTagMenuItems(null, othersMenu, item, listener, TagTreeModel.FOLDER_OTHERS);
return othersMenu; return othersMenu;
} }
private void addAddTagMenuItems(List<Integer> allowedTagTypes, JMenu addTagMenu, TreeItem item, AddTagActionListener listener) { private void addAddTagMenuItems(List<Integer> allowedTagTypes, JMenu addTagMenu, TreeItem item, AddTagActionListener listener, String parentFolder) {
if (allowedTagTypes == null) { if (allowedTagTypes == null) {
boolean gfx = mainPanel.getCurrentSwf().gfx; boolean gfx = mainPanel.getCurrentSwf().gfx;
@@ -1580,13 +1583,82 @@ public class TagTreeContextMenu extends JPopupMenu {
TreeNodeType type = AbstractTagTree.getTagNodeTypeFromTagClass(cl); TreeNodeType type = AbstractTagTree.getTagNodeTypeFromTagClass(cl);
tagItem.setIcon(TagTree.getIconForType(type)); tagItem.setIcon(TagTree.getIconForType(type));
tagItem.addActionListener((ActionEvent ae) -> { tagItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, cl); listener.call(ae, item, cl, null);
}); });
addTagMenu.add(tagItem); addTagMenu.add(tagItem);
} }
if (parentFolder == null) {
return;
}
switch (parentFolder) {
case TagTreeModel.FOLDER_SHAPES:
addTagMenu.addSeparator();
JMenuItem createShapeItem = new JMenuItem(AppStrings.translate("tag.shape.create"));
createShapeItem.setIcon(View.getIcon("importshape16"));
createShapeItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineShape4Tag.class, TreeNodeType.SHAPE);
});
addTagMenu.add(createShapeItem);
break;
case TagTreeModel.FOLDER_IMAGES:
addTagMenu.addSeparator();
JMenuItem createImageItem = new JMenuItem(AppStrings.translate("tag.image.create"));
createImageItem.setIcon(View.getIcon("importimage16"));
createImageItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineBitsLossless2Tag.class, TreeNodeType.IMAGE);
});
addTagMenu.add(createImageItem);
break;
case TagTreeModel.FOLDER_SPRITES:
addTagMenu.addSeparator();
JMenuItem createSpriteItem = new JMenuItem(AppStrings.translate("tag.sprite.create"));
createSpriteItem.setIcon(View.getIcon("importsprite16"));
createSpriteItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineSpriteTag.class, TreeNodeType.SPRITE);
});
addTagMenu.add(createSpriteItem);
break;
case TagTreeModel.FOLDER_MOVIES:
addTagMenu.addSeparator();
JMenuItem createMovieItem = new JMenuItem(AppStrings.translate("tag.movie.create"));
createMovieItem.setIcon(View.getIcon("importmovie16"));
createMovieItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineVideoStreamTag.class, TreeNodeType.MOVIE);
});
addTagMenu.add(createMovieItem);
break;
case TagTreeModel.FOLDER_SOUNDS:
addTagMenu.addSeparator();
JMenuItem createSoundItem = new JMenuItem(AppStrings.translate("tag.sound.create"));
createSoundItem.setIcon(View.getIcon("importsound16"));
createSoundItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineSoundTag.class, TreeNodeType.SOUND);
});
addTagMenu.add(createSoundItem);
break;
case TagTreeModel.FOLDER_FONTS:
addTagMenu.addSeparator();
JMenuItem createFontItem = new JMenuItem(AppStrings.translate("tag.font.create"));
createFontItem.setIcon(View.getIcon("importfont16"));
createFontItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineFont3Tag.class, TreeNodeType.FONT);
});
addTagMenu.add(createFontItem);
break;
case TagTreeModel.FOLDER_BINARY_DATA:
addTagMenu.addSeparator();
JMenuItem createBinaryDataItem = new JMenuItem(AppStrings.translate("tag.binaryData.create"));
createBinaryDataItem.setIcon(View.getIcon("importbinarydata16"));
createBinaryDataItem.addActionListener((ActionEvent ae) -> {
listener.call(ae, item, DefineBinaryDataTag.class, TreeNodeType.BINARY_DATA);
});
addTagMenu.add(createBinaryDataItem);
break;
}
} }
private void addTagInsideActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) { private void addTagInsideActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl, TreeNodeType createNodeType) {
int id = -1; int id = -1;
try { try {
id = cl.getDeclaredField("ID").getInt(null); id = cl.getDeclaredField("ID").getInt(null);
@@ -1629,13 +1701,14 @@ public class TagTreeContextMenu extends JPopupMenu {
swf.updateCharacters(); swf.updateCharacters();
mainPanel.refreshTree(swf); mainPanel.refreshTree(swf);
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t); mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t);
handleCreateFromFile(t, createNodeType);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
} }
} }
} }
private void addTagBeforeActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) { private void addTagBeforeActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl, TreeNodeType createNodeType) {
try { try {
SWF swf = (SWF) item.getOpenable(); SWF swf = (SWF) item.getOpenable();
Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf});
@@ -1669,12 +1742,13 @@ public class TagTreeContextMenu extends JPopupMenu {
swf.updateCharacters(); swf.updateCharacters();
mainPanel.refreshTree(swf); mainPanel.refreshTree(swf);
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t); mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t);
handleCreateFromFile(t, createNodeType);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
} }
} }
private void addTagAfterActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) { private void addTagAfterActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl, TreeNodeType createNodeType) {
try { try {
SWF swf = (SWF) item.getOpenable(); SWF swf = (SWF) item.getOpenable();
Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf});
@@ -1711,6 +1785,7 @@ public class TagTreeContextMenu extends JPopupMenu {
swf.updateCharacters(); swf.updateCharacters();
mainPanel.refreshTree(swf); mainPanel.refreshTree(swf);
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t); mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), t);
handleCreateFromFile(t, createNodeType);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
} }
@@ -3277,7 +3352,7 @@ public class TagTreeContextMenu extends JPopupMenu {
} }
} }
private void attachTagActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl) { private void attachTagActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl, TreeNodeType createNodeType) {
int id = -1; int id = -1;
try { try {
id = cl.getDeclaredField("ID").getInt(null); id = cl.getDeclaredField("ID").getInt(null);
@@ -3726,4 +3801,31 @@ public class TagTreeContextMenu extends JPopupMenu {
} }
} }
} }
private void handleCreateFromFile(Tag tag, TreeNodeType createNodeType) {
if (createNodeType == null) {
return;
}
boolean remove;
switch (createNodeType) {
case SPRITE:
remove = !mainPanel.replaceSpriteWithGif(tag);
break;
case SHAPE:
remove = !mainPanel.replaceNoFill(tag);
break;
case FONT:
remove = !mainPanel.fontEmbed(tag, true);
break;
default:
List<TreeItem> sel = new ArrayList<>();
sel.add(tag);
remove = !mainPanel.replace(sel, true);
break;
}
if (remove) {
tag.getTimelined().removeTag(tag);
mainPanel.refreshTree();
}
}
} }