Issue #1118 Loading characters through ImportAssets - show as readonly
icon
@@ -107,12 +107,14 @@ import com.jpexs.decompiler.flash.tags.base.DrawableTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.Exportable;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImportTag;
|
||||
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.RenderContext;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.timeline.AS2Package;
|
||||
@@ -161,6 +163,7 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -214,6 +217,9 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
@Internal
|
||||
public ReadOnlyTagList readOnlyTags;
|
||||
|
||||
@Internal
|
||||
public ReadOnlyTagList readOnlyLocalTags;
|
||||
|
||||
public boolean hasEndTag = true;
|
||||
|
||||
/**
|
||||
@@ -494,6 +500,20 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return exportName;
|
||||
}
|
||||
|
||||
public FontTag getFontByClass(String fontClass) {
|
||||
if (fontClass == null) {
|
||||
return null;
|
||||
}
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof FontTag) {
|
||||
if (fontClass.equals(((FontTag) t).getClassName())) {
|
||||
return (FontTag) t;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public FontTag getFont(int fontId) {
|
||||
CharacterTag characterTag = getCharacters().get(fontId);
|
||||
if (characterTag instanceof FontTag) {
|
||||
@@ -593,7 +613,13 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public int getNextCharacterId() {
|
||||
int max = 0;
|
||||
for (int characterId : getCharacters().keySet()) {
|
||||
Set<Integer> ids = new HashSet<>(getCharacters().keySet());
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ImportTag) {
|
||||
ids.addAll(((ImportTag) t).getAssets().keySet());
|
||||
}
|
||||
}
|
||||
for (int characterId : ids) {
|
||||
if (characterId > max) {
|
||||
max = characterId;
|
||||
}
|
||||
@@ -824,7 +850,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
sos.writeFIXED8(frameRate);
|
||||
sos.writeUI16(frameCount);
|
||||
|
||||
sos.writeTags(getTags());
|
||||
sos.writeTags(getLocalTags());
|
||||
if (hasEndTag) {
|
||||
sos.writeUI16(0);
|
||||
}
|
||||
@@ -1066,6 +1092,10 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
decompress(is, new NulStream(), true);
|
||||
}
|
||||
|
||||
public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy) throws IOException, InterruptedException {
|
||||
this(is, file, fileTitle, listener, parallelRead, checkOnly, lazy, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct SWF from stream
|
||||
*
|
||||
@@ -1076,10 +1106,11 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
* @param parallelRead Use parallel threads?
|
||||
* @param checkOnly Check only file validity
|
||||
* @param lazy
|
||||
* @param resolver Resolver for imported tags
|
||||
* @throws IOException
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy) throws IOException, InterruptedException {
|
||||
public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy, UrlResolver resolver) throws IOException, InterruptedException {
|
||||
this.file = file;
|
||||
this.fileTitle = fileTitle;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@@ -1112,11 +1143,15 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
this.tags = tags;
|
||||
readOnlyTags = null;
|
||||
readOnlyLocalTags = null;
|
||||
if (!checkOnly) {
|
||||
checkInvalidSprites();
|
||||
updateCharacters();
|
||||
assignExportNamesToSymbols();
|
||||
assignClassesToSymbols();
|
||||
if (resolver != null) {
|
||||
resolveImported(resolver);
|
||||
}
|
||||
SWFDecompilerPlugin.fireSwfParsed(this);
|
||||
} else {
|
||||
boolean hasNonUnknownTag = false;
|
||||
@@ -1139,6 +1174,94 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
getASMs(true); // Add scriptNames to ASMs
|
||||
}
|
||||
|
||||
private void resolveImported(UrlResolver resolver) {
|
||||
for (int p = 0; p < tags.size(); p++) {
|
||||
Tag t = tags.get(p);
|
||||
if (t instanceof ImportTag) {
|
||||
ImportTag importTag = (ImportTag) t;
|
||||
|
||||
SWF iSwf = resolver.resolveUrl(importTag.getUrl());
|
||||
if (iSwf != null) {
|
||||
Map<Integer, String> exportedMap1 = new HashMap<>();
|
||||
Map<Integer, String> classesMap1 = new HashMap<>();
|
||||
|
||||
for (Tag t2 : iSwf.tags) {
|
||||
if (t2 instanceof ExportAssetsTag) {
|
||||
ExportAssetsTag sc = (ExportAssetsTag) t2;
|
||||
Map<Integer, String> m2 = sc.getTagToNameMap();
|
||||
for (int key : m2.keySet()) {
|
||||
if (!exportedMap1.containsKey(key)) {
|
||||
exportedMap1.put(key, m2.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t2 instanceof SymbolClassTag) {
|
||||
SymbolClassTag sc = (SymbolClassTag) t2;
|
||||
Map<Integer, String> m2 = sc.getTagToNameMap();
|
||||
for (int key : m2.keySet()) {
|
||||
if (!classesMap1.containsKey(key)) {
|
||||
classesMap1.put(key, m2.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Map<String, Integer> exportedMap2 = new HashMap<>();
|
||||
for (int k : exportedMap1.keySet()) {
|
||||
exportedMap2.put(exportedMap1.get(k), k);
|
||||
}
|
||||
|
||||
Map<String, Integer> classesMap2 = new HashMap<>();
|
||||
for (int k : classesMap1.keySet()) {
|
||||
classesMap2.put(classesMap1.get(k), k);
|
||||
}
|
||||
|
||||
Map<Integer, String> importedMap1 = importTag.getAssets();
|
||||
Map<String, Integer> importedMap2 = new HashMap<>();
|
||||
for (int k : importedMap1.keySet()) {
|
||||
importedMap2.put(importedMap1.get(k), k);
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
for (String key : importedMap2.keySet()) {
|
||||
if (!exportedMap2.containsKey(key)) {
|
||||
continue; //?
|
||||
}
|
||||
int exportedId = exportedMap2.get(key);
|
||||
int importedId = importedMap2.get(key);
|
||||
for (Tag cht : iSwf.tags) {
|
||||
if ((cht instanceof CharacterIdTag) && (((CharacterIdTag) cht).getCharacterId() == exportedId) && !(cht instanceof PlaceObjectTypeTag) && !(cht instanceof RemoveTag)) {
|
||||
CharacterIdTag ch = (CharacterIdTag) cht;
|
||||
cht.setSwf(this);
|
||||
ch.setCharacterId(importedId);
|
||||
cht.setImported(true);
|
||||
tags.add(p + 1 + pos, cht);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int newId = getNextCharacterId();
|
||||
pos = 0;
|
||||
for (String key : classesMap2.keySet()) {
|
||||
int exportedId = classesMap2.get(key);
|
||||
int importedId = newId++;
|
||||
for (Tag cht : iSwf.tags) {
|
||||
if ((cht instanceof CharacterIdTag) && (((CharacterIdTag) cht).getCharacterId() == exportedId) && !(cht instanceof PlaceObjectTypeTag) && !(cht instanceof RemoveTag)) {
|
||||
CharacterIdTag ch = (CharacterIdTag) cht;
|
||||
cht.setSwf(this);
|
||||
ch.setCharacterId(importedId);
|
||||
cht.setImported(true);
|
||||
tags.add(p + 1 + pos, cht);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateCharacters();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return this;
|
||||
@@ -2338,6 +2461,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public void clearReadOnlyListCache() {
|
||||
readOnlyTags = null;
|
||||
readOnlyLocalTags = null;
|
||||
for (Tag tag : tags) {
|
||||
if (tag instanceof DefineSpriteTag) {
|
||||
((DefineSpriteTag) tag).clearReadOnlyListCache();
|
||||
@@ -3059,13 +3183,15 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
timelined.setModified(true);
|
||||
timelined.resetTimeline();
|
||||
} else // timeline should be always the swf here
|
||||
if (removeDependencies) {
|
||||
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
|
||||
timelined.setModified(true);
|
||||
} else {
|
||||
boolean modified = removeTagFromTimeline(tag, timelined.getTimeline());
|
||||
if (modified) {
|
||||
{
|
||||
if (removeDependencies) {
|
||||
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
|
||||
timelined.setModified(true);
|
||||
} else {
|
||||
boolean modified = removeTagFromTimeline(tag, timelined.getTimeline());
|
||||
if (modified) {
|
||||
timelined.setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3079,6 +3205,20 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return readOnlyTags;
|
||||
}
|
||||
|
||||
public ReadOnlyTagList getLocalTags() {
|
||||
if (readOnlyLocalTags == null) {
|
||||
List<Tag> localTags = new ArrayList<>();
|
||||
for (Tag t : tags) {
|
||||
if (!t.isImported()) {
|
||||
localTags.add(t);
|
||||
}
|
||||
}
|
||||
readOnlyLocalTags = new ReadOnlyTagList(localTags);
|
||||
}
|
||||
|
||||
return readOnlyLocalTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tag to the SWF
|
||||
*
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface UrlResolver {
|
||||
|
||||
public SWF resolveUrl(String url);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ public class Stage extends DisplayObject {
|
||||
startTime = System.currentTimeMillis();
|
||||
this.timelined = timelined;
|
||||
this.timeline = timelined != null ? timelined.getTimeline() : null;
|
||||
this.frame = timelined != null ? this.timeline.getFrame(0) : null;
|
||||
this.frame = timelined != null && this.timeline.getFrameCount() > 0 ? this.timeline.getFrame(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -359,7 +359,11 @@ public class DefineEditTextTag extends TextTag {
|
||||
private List<CharacterWithStyle> getTextWithStyle() {
|
||||
String str = "";
|
||||
TextStyle style = new TextStyle();
|
||||
style.font = swf.getFont(fontId);
|
||||
if (fontClass != null) {
|
||||
style.font = swf.getFontByClass(fontClass);
|
||||
} else {
|
||||
style.font = swf.getFont(fontId);
|
||||
}
|
||||
style.fontHeight = fontHeight;
|
||||
style.fontLeading = leading;
|
||||
if (hasTextColor) {
|
||||
@@ -991,10 +995,8 @@ public class DefineEditTextTag extends TextTag {
|
||||
if (Character.isWhitespace(c)) {
|
||||
lastWasWhiteSpace = true;
|
||||
}
|
||||
} else {
|
||||
if (multiline) {
|
||||
textModel.newParagraph();
|
||||
}
|
||||
} else if (multiline) {
|
||||
textModel.newParagraph();
|
||||
}
|
||||
prevChar = c;
|
||||
}
|
||||
@@ -1096,8 +1098,15 @@ public class DefineEditTextTag extends TextTag {
|
||||
}
|
||||
for (SameStyleTextRecord tr : line) {
|
||||
TEXTRECORD tr2 = new TEXTRECORD();
|
||||
tr2.styleFlagsHasFont = fontId != 0;
|
||||
tr2.fontId = fontId;
|
||||
int fid = fontId;
|
||||
if (fontClass != null) {
|
||||
FontTag ft = swf.getFontByClass(fontClass);
|
||||
if (ft != null) {
|
||||
fid = ft.getFontId();
|
||||
}
|
||||
}
|
||||
tr2.styleFlagsHasFont = fid != 0;
|
||||
tr2.fontId = fid;
|
||||
tr2.textHeight = tr.style.fontHeight;
|
||||
if (tr.style.textColor != null) {
|
||||
tr2.styleFlagsHasColor = true;
|
||||
|
||||
@@ -28,7 +28,9 @@ import com.jpexs.decompiler.flash.types.annotations.Table;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Makes portions of a SWF file available for import by other SWF files
|
||||
@@ -65,6 +67,19 @@ public class ExportAssetsTag extends SymbolClassTypeTag {
|
||||
names = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, String> getTagToNameMap() {
|
||||
Map<Integer, String> exportNames = new HashMap<>();
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
int tagId = tags.get(i);
|
||||
String name = names.get(i);
|
||||
if ((!exportNames.containsKey(tagId)) && (!exportNames.containsValue(name))) {
|
||||
exportNames.put(tagId, name);
|
||||
}
|
||||
}
|
||||
return exportNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
||||
@@ -28,7 +28,9 @@ import com.jpexs.decompiler.flash.types.annotations.Table;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -50,6 +52,19 @@ public class SymbolClassTag extends SymbolClassTypeTag {
|
||||
@Table(value = "symbols", itemName = "symbol")
|
||||
public List<String> names;
|
||||
|
||||
@Override
|
||||
public Map<Integer, String> getTagToNameMap() {
|
||||
Map<Integer, String> exportNames = new HashMap<>();
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
int tagId = tags.get(i);
|
||||
String name = names.get(i);
|
||||
if ((!exportNames.containsKey(tagId)) && (!exportNames.containsValue(name))) {
|
||||
exportNames.put(tagId, name);
|
||||
}
|
||||
}
|
||||
return exportNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
||||
@@ -84,6 +84,17 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
@Internal
|
||||
private boolean modified;
|
||||
|
||||
@Internal
|
||||
protected boolean imported = false;
|
||||
|
||||
public void setImported(boolean imported) {
|
||||
this.imported = imported;
|
||||
}
|
||||
|
||||
public boolean isImported() {
|
||||
return imported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Original tag data
|
||||
*/
|
||||
@@ -573,6 +584,10 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return isImported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNeededCharacters(Set<Integer> needed) {
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.tags.base;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -29,4 +30,6 @@ public abstract class SymbolClassTypeTag extends Tag {
|
||||
public SymbolClassTypeTag(SWF swf, int id, String name, ByteArrayRange data) {
|
||||
super(swf, id, name, data);
|
||||
}
|
||||
|
||||
public abstract Map<Integer, String> getTagToNameMap();
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ public class Timeline {
|
||||
|
||||
public Frame getFrame(int index) {
|
||||
ensureInitialized();
|
||||
if (index >= frames.size()) {
|
||||
return null;
|
||||
}
|
||||
return frames.get(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -219,6 +219,9 @@ public class FontPanel extends JPanel {
|
||||
|
||||
setAllowSave(true);
|
||||
setEditable(false);
|
||||
boolean readOnly = ((Tag) ft).isReadOnly();
|
||||
addCharsPanel.setVisible(!readOnly);
|
||||
buttonEdit.setVisible(!readOnly);
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
|
||||
@@ -26,8 +26,10 @@ import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.SWFSourceInfo;
|
||||
import com.jpexs.decompiler.flash.SearchMode;
|
||||
import com.jpexs.decompiler.flash.SwfOpenException;
|
||||
import com.jpexs.decompiler.flash.UrlResolver;
|
||||
import com.jpexs.decompiler.flash.Version;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration;
|
||||
import com.jpexs.decompiler.flash.console.CommandLineArgumentParser;
|
||||
@@ -653,18 +655,149 @@ public class Main {
|
||||
}
|
||||
} else {
|
||||
InputStream fInputStream = inputStream;
|
||||
|
||||
final String[] yesno = new String[]{AppStrings.translate("button.yes"), AppStrings.translate("button.no"), AppStrings.translate("button.yes.all"), AppStrings.translate("button.no.all")};
|
||||
|
||||
CancellableWorker<SWF> worker = new CancellableWorker<SWF>() {
|
||||
@Override
|
||||
public SWF doInBackground() throws Exception {
|
||||
|
||||
private boolean yestoall = false;
|
||||
private boolean notoall = false;
|
||||
|
||||
private SWF open(InputStream is, String file, String fileTitle) throws IOException, InterruptedException {
|
||||
final CancellableWorker worker = this;
|
||||
SWF swf = new SWF(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle(), new ProgressListener() {
|
||||
|
||||
SWF swf = new SWF(is, file, fileTitle, new ProgressListener() {
|
||||
@Override
|
||||
public void progress(int p) {
|
||||
startWork(AppStrings.translate("work.reading.swf"), p, worker);
|
||||
}
|
||||
}, Configuration.parallelSpeedUp.get());
|
||||
}, Configuration.parallelSpeedUp.get(), false, true, new UrlResolver() {
|
||||
@Override
|
||||
public SWF resolveUrl(final String url) {
|
||||
int opt = -1;
|
||||
if (!(yestoall || notoall)) {
|
||||
opt = View.showOptionDialog(null, AppStrings.translate("message.imported.swf").replace("%url%", url), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, AppStrings.translate("button.yes"));
|
||||
if (opt == 2) {
|
||||
yestoall = true;
|
||||
}
|
||||
if (opt == 3) {
|
||||
notoall = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (yestoall) {
|
||||
opt = 0; // yes
|
||||
} else if (notoall) {
|
||||
opt = 1; // no
|
||||
}
|
||||
|
||||
if (opt == 1) //no
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
try {
|
||||
URL u = new URL(url);
|
||||
return open(u.openStream(), null, url); //?
|
||||
} catch (Exception ex) {
|
||||
//ignore
|
||||
}
|
||||
} else {
|
||||
File f = new File(new File(file).getParentFile(), url);
|
||||
if (f.exists()) {
|
||||
try {
|
||||
return open(new FileInputStream(f), f.getAbsolutePath(), f.getName());
|
||||
} catch (Exception ex) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference<SWF> ret = new Reference<>(null);
|
||||
View.execInEventDispatch(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
while (JOptionPane.YES_OPTION == View.showConfirmDialog(null, AppStrings.translate("message.imported.swf.manually").replace("%url%", url), AppStrings.translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE)) {
|
||||
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
|
||||
FileFilter allSupportedFilter = new FileFilter() {
|
||||
private final String[] supportedExtensions = new String[]{".swf", ".gfx"};
|
||||
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
String name = f.getName().toLowerCase();
|
||||
for (String ext : supportedExtensions) {
|
||||
if (name.endsWith(ext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return f.isDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
String exts = Helper.joinStrings(supportedExtensions, "*%s", "; ");
|
||||
return AppStrings.translate("filter.supported") + " (" + exts + ")";
|
||||
}
|
||||
};
|
||||
fc.setFileFilter(allSupportedFilter);
|
||||
FileFilter swfFilter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return AppStrings.translate("filter.swf");
|
||||
}
|
||||
};
|
||||
fc.addChoosableFileFilter(swfFilter);
|
||||
|
||||
FileFilter gfxFilter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File f) {
|
||||
return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return AppStrings.translate("filter.gfx");
|
||||
}
|
||||
};
|
||||
fc.addChoosableFileFilter(gfxFilter);
|
||||
fc.setAcceptAllFileFilterUsed(false);
|
||||
JFrame f = new JFrame();
|
||||
View.setWindowIcon(f);
|
||||
int returnVal = fc.showOpenDialog(f);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
|
||||
File selFile = Helper.fixDialogFile(fc.getSelectedFile());
|
||||
try {
|
||||
ret.setVal(open(new FileInputStream(selFile), selFile.getAbsolutePath(), selFile.getName()));
|
||||
break;
|
||||
} catch (Exception ex) {
|
||||
//ignore;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return ret.getVal();
|
||||
}
|
||||
});
|
||||
return swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public SWF doInBackground() throws Exception {
|
||||
return open(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle());
|
||||
}
|
||||
};
|
||||
if (loadingDialog != null) {
|
||||
loadingDialog.setWroker(worker);
|
||||
|
||||
@@ -833,10 +833,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
if (View.showConfirmDialog(this, translate("message.confirm.closeAll"), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (View.showConfirmDialog(this, translate("message.confirm.close").replace("{swfName}", swfList.toString()), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) {
|
||||
return false;
|
||||
}
|
||||
} else if (View.showConfirmDialog(this, translate("message.confirm.close").replace("{swfName}", swfList.toString()), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1556,6 +1554,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
actionPanel.editor.refreshMarkers();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public void debuggerBreakAt(SWF swf, String cls, int line) {
|
||||
View.execInEventDispatchLater(new Runnable() {
|
||||
@@ -1570,7 +1569,6 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
});
|
||||
|
||||
}*/
|
||||
|
||||
public void gotoScriptName(SWF swf, String scriptName) {
|
||||
if (swf == null) {
|
||||
return;
|
||||
@@ -2166,10 +2164,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
List<TreeItem> sel = tagTree.getAllSelected();
|
||||
if (!onlySel) {
|
||||
sel = null;
|
||||
} else {
|
||||
if (sel.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
} else if (sel.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final ExportDialog export = new ExportDialog(sel);
|
||||
if (export.showExportDialog() == AppDialog.OK_OPTION) {
|
||||
@@ -2818,10 +2814,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
if (detailPanel.isVisible()) {
|
||||
detailPanel.setVisible(false);
|
||||
}
|
||||
} else {
|
||||
if (!detailPanel.isVisible()) {
|
||||
detailPanel.setVisible(true);
|
||||
}
|
||||
} else if (!detailPanel.isVisible()) {
|
||||
detailPanel.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3194,7 +3188,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
showCard(CARDACTIONSCRIPTPANEL);
|
||||
} else if (treeItem instanceof ImageTag) {
|
||||
ImageTag imageTag = (ImageTag) treeItem;
|
||||
previewPanel.setImageReplaceButtonVisible(imageTag.importSupported(), imageTag instanceof DefineBitsJPEG3Tag || imageTag instanceof DefineBitsJPEG4Tag);
|
||||
previewPanel.setImageReplaceButtonVisible(!((Tag) imageTag).isReadOnly() && imageTag.importSupported(), imageTag instanceof DefineBitsJPEG3Tag || imageTag instanceof DefineBitsJPEG4Tag);
|
||||
previewPanel.showImagePanel(imageTag.getImage());
|
||||
showCard(CARDPREVIEWPANEL);
|
||||
} else if ((treeItem instanceof DrawableTag) && (!(treeItem instanceof TextTag)) && (!(treeItem instanceof FontTag)) && internalViewer) {
|
||||
@@ -3227,7 +3221,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
showCard(CARDPREVIEWPANEL);
|
||||
} else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) {
|
||||
previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32")));
|
||||
previewPanel.setImageReplaceButtonVisible(treeItem instanceof DefineSoundTag, false);
|
||||
previewPanel.setImageReplaceButtonVisible(((Tag) treeItem).isReadOnly() && (treeItem instanceof DefineSoundTag), false);
|
||||
try {
|
||||
SoundTagPlayer soundThread = new SoundTagPlayer((SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true);
|
||||
previewPanel.setMedia(soundThread);
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.helpers.HighlightedText;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
@@ -59,6 +60,8 @@ public class TextPanel extends JPanel implements TagEditorPanel {
|
||||
|
||||
private final LineMarkedEditorPane textValue;
|
||||
|
||||
private final JPanel buttonsPanel;
|
||||
|
||||
private final JButton textEditButton;
|
||||
|
||||
private final JButton textSaveButton;
|
||||
@@ -132,7 +135,7 @@ public class TextPanel extends JPanel implements TagEditorPanel {
|
||||
topPanel.add(textButtonsPanel);
|
||||
add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
JPanel buttonsPanel = new JPanel(new FlowLayout());
|
||||
buttonsPanel = new JPanel(new FlowLayout());
|
||||
textEditButton = createButton("button.edit", "edit16", null, e -> editText());
|
||||
textSaveButton = createButton("button.save", "save16", null, e -> saveText(true));
|
||||
textCancelButton = createButton("button.cancel", "cancel16", null, e -> cancelText());
|
||||
@@ -174,6 +177,17 @@ public class TextPanel extends JPanel implements TagEditorPanel {
|
||||
textValue.setCaretPosition(0);
|
||||
setModified(false);
|
||||
setEditText(false);
|
||||
boolean readOnly = ((Tag) textTag).isReadOnly();
|
||||
textValue.setEditable(!readOnly);
|
||||
buttonsPanel.setVisible(!readOnly);
|
||||
textAlignLeftButton.setVisible(!readOnly);
|
||||
textAlignCenterButton.setVisible(!readOnly);
|
||||
textAlignRightButton.setVisible(!readOnly);
|
||||
textAlignJustifyButton.setVisible(!readOnly);
|
||||
decreaseTranslateXButton.setVisible(!readOnly);
|
||||
increaseTranslateXButton.setVisible(!readOnly);
|
||||
changeCaseButton.setVisible(!readOnly);
|
||||
undoChangesButton.setVisible(!readOnly);
|
||||
}
|
||||
|
||||
private boolean isModified() {
|
||||
|
||||
|
Before Width: | Height: | Size: 864 B After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 19 KiB |
@@ -702,3 +702,6 @@ menu.file.start.debugpcode = Debug P-code
|
||||
#after 7.1.2
|
||||
button.replaceNoFill = Replace - Update bounds...
|
||||
message.warning.svgImportExperimental = Not all SVG features are supported. Only solid color fill mode is supported. Please check the log after import.
|
||||
|
||||
message.imported.swf = The SWF file uses assets from an imported SWF file:\n%url%\nDo you want the assets to be loaded from that URL?
|
||||
message.imported.swf.manually = Cannot load imported SWF\n%url%\nThe file or URL does not exist.\nDo you want to select local file?
|
||||
@@ -206,19 +206,27 @@ public class TagTree extends JTree {
|
||||
isModified = true;
|
||||
}
|
||||
}*/
|
||||
boolean isReadOnly = false;
|
||||
if (val instanceof Tag) {
|
||||
isReadOnly = ((Tag) val).isReadOnly();
|
||||
}
|
||||
|
||||
boolean isModified = val.isModified();
|
||||
if (isModified) {
|
||||
if (boldFont == null) {
|
||||
Font font = getFont();
|
||||
boldFont = font.deriveFont(Font.BOLD);
|
||||
}
|
||||
} else {
|
||||
if (plainFont == null) {
|
||||
Font font = getFont();
|
||||
plainFont = font.deriveFont(Font.PLAIN);
|
||||
}
|
||||
} else if (plainFont == null) {
|
||||
Font font = getFont();
|
||||
plainFont = font.deriveFont(Font.PLAIN);
|
||||
}
|
||||
setFont(isModified ? boldFont : plainFont);
|
||||
if (isReadOnly) {
|
||||
setForeground(new Color(0xcc, 0xcc, 0xcc));
|
||||
} else {
|
||||
setForeground(Color.BLACK);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||