diff --git a/libsrc/avi/src/org/monte/media/AbstractVideoCodec.java b/libsrc/avi/src/org/monte/media/AbstractVideoCodec.java
index f180e7233..0f7b53bb5 100644
--- a/libsrc/avi/src/org/monte/media/AbstractVideoCodec.java
+++ b/libsrc/avi/src/org/monte/media/AbstractVideoCodec.java
@@ -1,9 +1,9 @@
/*
* @(#)AbstractVideoCodec.java
- *
+ *
* Copyright (c) 2011 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
- *
+ *
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
@@ -21,7 +21,8 @@ import java.awt.image.DirectColorModel;
import java.awt.image.WritableRaster;
import java.io.IOException;
import javax.imageio.stream.ImageOutputStream;
-import static org.monte.media.VideoFormatKeys.*;
+import static org.monte.media.VideoFormatKeys.HeightKey;
+import static org.monte.media.VideoFormatKeys.WidthKey;
/**
* {@code AbstractVideoCodec}.
@@ -37,7 +38,10 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
super(supportedInputFormats, supportedOutputFormats);
}
- /** Gets 8-bit indexed pixels from a buffer. Returns null if conversion failed. */
+ /**
+ * Gets 8-bit indexed pixels from a buffer. Returns null if conversion
+ * failed.
+ */
protected byte[] getIndexed8(Buffer buf) {
if (buf.data instanceof byte[]) {
return (byte[]) buf.data;
@@ -51,7 +55,9 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
return null;
}
- /** Gets 15-bit RGB pixels from a buffer. Returns null if conversion failed. */
+ /**
+ * Gets 15-bit RGB pixels from a buffer. Returns null if conversion failed.
+ */
protected short[] getRGB15(Buffer buf) {
if (buf.data instanceof int[]) {
return (short[]) buf.data;
@@ -80,7 +86,11 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
}
return null;
}
- /** Gets 16-bit RGB-5-6-5 pixels from a buffer. Returns null if conversion failed. */
+
+ /**
+ * Gets 16-bit RGB-5-6-5 pixels from a buffer. Returns null if conversion
+ * failed.
+ */
protected short[] getRGB16(Buffer buf) {
if (buf.data instanceof int[]) {
return (short[]) buf.data;
@@ -110,8 +120,9 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
return null;
}
-
- /** Gets 24-bit RGB pixels from a buffer. Returns null if conversion failed. */
+ /**
+ * Gets 24-bit RGB pixels from a buffer. Returns null if conversion failed.
+ */
protected int[] getRGB24(Buffer buf) {
if (buf.data instanceof int[]) {
return (int[]) buf.data;
@@ -133,7 +144,9 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
return null;
}
- /** Gets 32-bit ARGB pixels from a buffer. Returns null if conversion failed. */
+ /**
+ * Gets 32-bit ARGB pixels from a buffer. Returns null if conversion failed.
+ */
protected int[] getARGB32(Buffer buf) {
if (buf.data instanceof int[]) {
return (int[]) buf.data;
@@ -155,13 +168,16 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
return null;
}
- /** Gets a buffered image from a buffer. Returns null if conversion failed. */
+ /**
+ * Gets a buffered image from a buffer. Returns null if conversion failed.
+ */
protected BufferedImage getBufferedImage(Buffer buf) {
if (buf.data instanceof BufferedImage) {
return (BufferedImage) buf.data;
}
return null;
}
+
private byte[] byteBuf = new byte[4];
protected void writeInt24(ImageOutputStream out, int v) throws IOException {
@@ -216,7 +232,9 @@ public abstract class AbstractVideoCodec extends AbstractCodec {
out.write(b, 0, len * 3);
}
- /** Copies a buffered image. */
+ /**
+ * Copies a buffered image.
+ */
protected static BufferedImage copyImage(BufferedImage img) {
ColorModel cm = img.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
diff --git a/libsrc/avi/src/org/monte/media/DefaultRegistry.java b/libsrc/avi/src/org/monte/media/DefaultRegistry.java
index 16496597b..813cbf2a0 100644
--- a/libsrc/avi/src/org/monte/media/DefaultRegistry.java
+++ b/libsrc/avi/src/org/monte/media/DefaultRegistry.java
@@ -1,9 +1,9 @@
/*
- * @(#)DefaultRegistry.java
- *
+ * @(#)DefaultRegistry.java
+ *
* Copyright (c) 2011 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
- *
+ *
* You may not use, copy or modify this file, except in compliance onlyWith the
* license agreement you entered into onlyWith Werner Randelshofer.
* For details see accompanying license terms.
@@ -16,13 +16,41 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
-import static org.monte.media.VideoFormatKeys.*;
-import static org.monte.media.AudioFormatKeys.*;
+import static org.monte.media.AudioFormatKeys.ENCODING_AVI_PCM;
+import static org.monte.media.AudioFormatKeys.ENCODING_PCM_SIGNED;
+import static org.monte.media.AudioFormatKeys.ENCODING_PCM_UNSIGNED;
+import static org.monte.media.AudioFormatKeys.ENCODING_QUICKTIME_IN24_PCM;
+import static org.monte.media.AudioFormatKeys.ENCODING_QUICKTIME_IN32_PCM;
+import static org.monte.media.AudioFormatKeys.ENCODING_QUICKTIME_RAW_PCM;
+import static org.monte.media.AudioFormatKeys.ENCODING_QUICKTIME_SOWT_PCM;
+import static org.monte.media.AudioFormatKeys.ENCODING_QUICKTIME_TWOS_PCM;
+import static org.monte.media.FormatKeys.EncodingKey;
+import static org.monte.media.FormatKeys.MIME_ANIM;
+import static org.monte.media.FormatKeys.MIME_AVI;
+import static org.monte.media.FormatKeys.MIME_JAVA;
+import static org.monte.media.FormatKeys.MIME_QUICKTIME;
+import org.monte.media.FormatKeys.MediaType;
+import static org.monte.media.FormatKeys.MediaTypeKey;
+import static org.monte.media.FormatKeys.MimeTypeKey;
+import static org.monte.media.VideoFormatKeys.COMPRESSOR_NAME_AVI_TECHSMITH_SCREEN_CAPTURE;
+import static org.monte.media.VideoFormatKeys.CompressorNameKey;
+import static org.monte.media.VideoFormatKeys.ENCODING_AVI_DIB;
+import static org.monte.media.VideoFormatKeys.ENCODING_AVI_DOSBOX_SCREEN_CAPTURE;
+import static org.monte.media.VideoFormatKeys.ENCODING_AVI_MJPG;
+import static org.monte.media.VideoFormatKeys.ENCODING_AVI_PNG;
+import static org.monte.media.VideoFormatKeys.ENCODING_AVI_RLE;
+import static org.monte.media.VideoFormatKeys.ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE;
+import static org.monte.media.VideoFormatKeys.ENCODING_BITMAP_IMAGE;
+import static org.monte.media.VideoFormatKeys.ENCODING_BUFFERED_IMAGE;
+import static org.monte.media.VideoFormatKeys.ENCODING_QUICKTIME_ANIMATION;
+import static org.monte.media.VideoFormatKeys.ENCODING_QUICKTIME_JPEG;
+import static org.monte.media.VideoFormatKeys.ENCODING_QUICKTIME_PNG;
+import static org.monte.media.VideoFormatKeys.ENCODING_QUICKTIME_RAW;
/**
- * {@code DefaultRegistry}.
+ * {@code DefaultRegistry}.
*
- * FIXME - The registry should be read from a file.
+ * FIXME - The registry should be read from a file.
*
* @author Werner Randelshofer
* @version $Id: DefaultRegistry.java 299 2013-01-03 07:40:18Z werner $
@@ -30,8 +58,11 @@ import static org.monte.media.AudioFormatKeys.*;
public class DefaultRegistry extends Registry {
private HashMap> codecMap;
+
private HashMap> readerMap;
+
private HashMap> writerMap;
+
private HashMap fileFormatMap;
@Override
@@ -52,7 +83,9 @@ public class DefaultRegistry extends Registry {
private static class RegistryEntry {
Format inputFormat;
+
Format outputFormat;
+
String className;
public RegistryEntry(Format inputFormat, Format outputFormat, String className) {
@@ -147,8 +180,8 @@ public class DefaultRegistry extends Registry {
"org.monte.media.png.PNGCodec");
putBidiCodec(
- new Format(MediaTypeKey, MediaType.VIDEO, MimeTypeKey, MIME_QUICKTIME,
- EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, CompressorNameKey, COMPRESSOR_NAME_AVI_TECHSMITH_SCREEN_CAPTURE),
+ new Format(MediaTypeKey, MediaType.VIDEO, MimeTypeKey, MIME_QUICKTIME,
+ EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, CompressorNameKey, COMPRESSOR_NAME_AVI_TECHSMITH_SCREEN_CAPTURE),
new Format(MediaTypeKey, MediaType.VIDEO, MimeTypeKey, MIME_JAVA, EncodingKey, ENCODING_BUFFERED_IMAGE),
"org.monte.media.avi.TechSmithCodec");
@@ -197,7 +230,6 @@ public class DefaultRegistry extends Registry {
new Format(MediaTypeKey, MediaType.AUDIO, MimeTypeKey, MIME_QUICKTIME, EncodingKey, ENCODING_QUICKTIME_RAW_PCM),
"org.monte.media.quicktime.QuickTimePCMAudioCodec");
-
putReader(new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI), "org.monte.media.avi.AVIReader");
putReader(new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_QUICKTIME), "org.monte.media.quicktime.QuickTimeReader");
putReader(new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_ANIM), "org.monte.media.anim.ANIMReader");
@@ -211,10 +243,12 @@ public class DefaultRegistry extends Registry {
}
/**
- *
- * @param inputFormat Must have {@code MediaTypeKey}, {@code EncodingKey}, {@code MimeTypeKey}.
- * @param outputFormat Must have {@code MediaTypeKey}, {@code EncodingKey}, {@code MimeTypeKey}.
- * @param codecClass
+ *
+ * @param inputFormat Must have {@code MediaTypeKey}, {@code EncodingKey},
+ * {@code MimeTypeKey}.
+ * @param outputFormat Must have {@code MediaTypeKey}, {@code EncodingKey},
+ * {@code MimeTypeKey}.
+ * @param codecClass
*/
public void putBidiCodec(Format inputFormat, Format outputFormat, String codecClass) {
putCodec(inputFormat, outputFormat, codecClass);
@@ -222,10 +256,12 @@ public class DefaultRegistry extends Registry {
}
/**
- *
- * @param inputFormat Must have {@code MediaTypeKey}, {@code EncodingKey}, {@code MimeTypeKey}.
- * @param outputFormat Must have {@code MediaTypeKey}, {@code EncodingKey}, {@code MimeTypeKey}.
- * @param codecClass
+ *
+ * @param inputFormat Must have {@code MediaTypeKey}, {@code EncodingKey},
+ * {@code MimeTypeKey}.
+ * @param outputFormat Must have {@code MediaTypeKey}, {@code EncodingKey},
+ * {@code MimeTypeKey}.
+ * @param codecClass
*/
@Override
public void putCodec(Format inputFormat, Format outputFormat, String codecClass) {
@@ -244,9 +280,9 @@ public class DefaultRegistry extends Registry {
}
/**
- *
+ *
* @param fileFormat Must have {@code MediaTypeKey}, {@code MimeTypeKey}.
- * @param readerClass
+ * @param readerClass
*/
@Override
public void putReader(Format fileFormat, String readerClass) {
@@ -261,9 +297,9 @@ public class DefaultRegistry extends Registry {
}
/**
- *
+ *
* @param fileFormat Must have {@code MediaTypeKey}, {@code MimeTypeKey}.
- * @param writerClass
+ * @param writerClass
*/
@Override
public void putWriter(Format fileFormat, String writerClass) {
@@ -380,16 +416,14 @@ public class DefaultRegistry extends Registry {
@Override
public void unregisterCodec(String codecClass) {
- for (Map.Entry> i:codecMap.entrySet()) {
- LinkedList ll=i.getValue();
- for (Iterator j=ll.iterator();j.hasNext();) {
- RegistryEntry e=j.next();
+ for (Map.Entry> i : codecMap.entrySet()) {
+ LinkedList ll = i.getValue();
+ for (Iterator j = ll.iterator(); j.hasNext();) {
+ RegistryEntry e = j.next();
if (e.className.equals(codecClass)) {
j.remove();
}
}
}
}
-
-
}
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 de0f5f104..2ed98b9b4 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
@@ -278,7 +278,7 @@ public final class SWF implements SWFContainerItem, Timelined {
@Internal
public SWFBundle bundle;
-
+
@Internal
private Timeline timeline;
@@ -865,6 +865,15 @@ public final class SWF implements SWFContainerItem, Timelined {
return this;
}
+ public SWF getRootSwf() {
+ SWF result = this;
+ while (result.binaryData != null) {
+ result = result.binaryData.getSwf();
+ }
+
+ return result;
+ }
+
public String getFile() {
return file;
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java
index 8840cacc0..e5a941f69 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java
@@ -34,16 +34,16 @@ public class SWFList implements List, SWFContainerItem {
public String name;
- //public boolean isBundle;
-
public SWFBundle bundle;
- //public Class bundleClass;
-
public SWFSourceInfo sourceInfo;
public List swfs = new ArrayList<>();
+ public boolean isBundle() {
+ return bundle != null;
+ }
+
@Override
public SWF getSwf() {
throw new UnsupportedOperationException("Not supported.");
@@ -51,7 +51,7 @@ public class SWFList implements List, SWFContainerItem {
@Override
public String toString() {
- if (bundle != null) {
+ if (isBundle()) {
return name;
} else {
return swfs.get(0).getFileTitle();
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java
index a94c70d83..fba9f8e36 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java
@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.treeitems;
import com.jpexs.decompiler.flash.SWF;
-import com.jpexs.decompiler.flash.SWFBundle;
/**
*
diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java
index c5cad702c..02aebb284 100644
--- a/src/com/jpexs/decompiler/flash/gui/Main.java
+++ b/src/com/jpexs/decompiler/flash/gui/Main.java
@@ -71,15 +71,11 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.Proxy;
-import java.net.Socket;
-import java.net.SocketAddress;
import java.net.URL;
import java.net.URLConnection;
-import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -411,7 +407,7 @@ public class Main {
}
public static void saveFile(SWF swf, String outfile, SaveFileMode mode) throws IOException {
- if (mode == SaveFileMode.SAVEAS && swf.swfList.bundle==null) {
+ if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) {
swf.setFile(outfile);
swf.swfList.sourceInfo.setFile(outfile);
}
@@ -505,7 +501,7 @@ public class Main {
loadingDialog.setVisible(false);
shouldCloseWhenClosingLoadingDialog = false;
- final SWF fswf = firstSWF;
+ final SWF fswf = firstSWF;
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
@@ -860,7 +856,6 @@ public class Main {
mainFrame.setVisible(true);
}
});
-
}
private static void offerAssociation() {
diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java
index e99049333..670aa3331 100644
--- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java
+++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java
@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
-import com.jpexs.decompiler.flash.SWFBundle;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.console.ContextMenuTools;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
@@ -729,7 +728,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu implements ActionListener
closeFileMenu.setEnabled(swfLoaded);
closeAllFilesMenu.setEnabled(swfLoaded);
- boolean isBundle = swfLoaded && (swf.swfList != null) && (swf.swfList.bundle != null);
+ boolean isBundle = swfLoaded && (swf.swfList != null) && (swf.swfList.isBundle());
saveCommandButton.setEnabled(swfLoaded && ((!isBundle) || (!swf.swfList.bundle.isReadOnly())));
saveasCommandButton.setEnabled(swfLoaded);
saveasexeCommandButton.setEnabled(swfLoaded);
diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
index 087e73e87..50f0d3f98 100644
--- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
@@ -67,6 +67,7 @@ import com.jpexs.decompiler.flash.gui.action.ActionPanel;
import com.jpexs.decompiler.flash.gui.dumpview.DumpTree;
import com.jpexs.decompiler.flash.gui.dumpview.DumpTreeModel;
import com.jpexs.decompiler.flash.gui.dumpview.DumpViewPanel;
+import com.jpexs.decompiler.flash.gui.helpers.ObservableList;
import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import com.jpexs.decompiler.flash.gui.tagtree.TagTree;
import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel;
@@ -200,7 +201,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
private final MainFrame mainFrame;
- private final List swfs;
+ private final ObservableList swfs;
private ABCPanel abcPanel;
@@ -409,7 +410,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
mainFrame.setTitle(ApplicationInfo.applicationVerName);
setLayout(new BorderLayout());
- swfs = new ArrayList<>();
+ swfs = new ObservableList<>();
detailPanel = new JPanel();
detailPanel.setLayout(new CardLayout());
@@ -615,6 +616,31 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
showView(getCurrentView());
updateUi();
+ this.swfs.addCollectionChangedListener((e) -> {
+ TagTreeModel ttm = tagTree.getModel();
+ if (ttm != null) {
+ ttm.updateSwfs(e);
+ TreeItem root = ttm.getRoot();
+ int childCount = ttm.getChildCount(root);
+ for (int i = 0; i < childCount; i++) {
+ tagTree.expandPath(new TreePath(new Object[]{root, ttm.getChild(root, i)}));
+ }
+ }
+
+ DumpTreeModel dtm = dumpTree.getModel();
+ if (dtm != null) {
+ List> expandedNodes = View.getExpandedNodes(dumpTree);
+ dtm.updateSwfs();
+ View.expandTreeNodes(dumpTree, expandedNodes);
+ DumpInfo root = dtm.getRoot();
+ int childCount = dtm.getChildCount(root);
+ for (int i = 0; i < childCount; i++) {
+ dumpTree.expandPath(new TreePath(new Object[]{root, dtm.getChild(root, i)}));
+ dumpTree.expandRow(i);
+ }
+ }
+ });
+
//Opening files with drag&drop to main window
enableDrop(true);
}
@@ -647,7 +673,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
if (swf != null) {
updateUi(swf);
}
- refreshTree();
}
private ABCPanel getABCPanel() {
@@ -748,7 +773,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
oldItem = null;
clear();
updateUi();
- refreshTree();
return true;
}
@@ -772,7 +796,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
oldItem = null;
clear();
updateUi();
- refreshTree();
return true;
}
@@ -1167,7 +1190,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
if (treeItem instanceof Timelined) {
Timelined t = (Timelined) treeItem;
Timeline tim = t.getTimeline();
- Frame f = ((TagTreeModel) tagTree.getModel()).getFrame(treeItem.getSwf(), t, frame);
+ Frame f = tagTree.getModel().getFrame(treeItem.getSwf(), t, frame);
if (f != null) {
setTagTreeSelectedNode(f);
}
@@ -1383,8 +1406,8 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
public void setTagTreeSelectedNode(TreeItem treeItem) {
- TagTreeModel ttm = (TagTreeModel) tagTree.getModel();
- TreePath tp = ttm.getTagPath(treeItem);
+ TagTreeModel ttm = tagTree.getModel();
+ TreePath tp = ttm.getTreePath(treeItem);
if (tp != null) {
tagTree.setSelectionPath(tp);
tagTree.scrollPathToVisible(tp);
@@ -1928,24 +1951,26 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
public void refreshTree() {
+ refreshTree(null);
+ }
+
+ public void refreshTree(SWF swf) {
clear();
showCard(CARDEMPTYPANEL);
TreeItem treeItem = tagTree.getCurrentTreeItem();
- DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent();
- if (tagTree.getModel() != null) {
- View.refreshTree(tagTree, new TagTreeModel(swfs, Configuration.tagTreeShowEmptyFolders.get()));
- }
-
- if (dumpTree.getModel() != null) {
- View.refreshTree(dumpTree, new DumpTreeModel(swfs));
+ TagTreeModel ttm = tagTree.getModel();
+ if (ttm != null) {
+ List> expandedNodes = View.getExpandedNodes(tagTree);
+ ttm.updateSwf(swf);
+ View.expandTreeNodes(tagTree, expandedNodes);
}
if (treeItem != null) {
- setTagTreeSelectedNode(treeItem);
- }
- if (dumpInfo != null) {
- setDumpTreeSelectedNode(dumpInfo);
+ SWF treeItemSwf = treeItem.getSwf().getRootSwf();
+ if (swfs.contains(treeItemSwf.swfList)) {
+ setTagTreeSelectedNode(treeItem);
+ }
}
reload(true);
@@ -2232,7 +2257,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
TreeItem treeItem = (TreeItem) e.getPath().getLastPathComponent();
if (!(treeItem instanceof SWFList)) {
- SWF swf = treeItem.getSwf();
+ SWF swf = treeItem.getSwf();
if (swfs.isEmpty()) {
// show welcome panel after closing swfs
updateUi();
diff --git a/src/com/jpexs/decompiler/flash/gui/View.java b/src/com/jpexs/decompiler/flash/gui/View.java
index 3ad442bc0..426781298 100644
--- a/src/com/jpexs/decompiler/flash/gui/View.java
+++ b/src/com/jpexs/decompiler/flash/gui/View.java
@@ -483,7 +483,7 @@ public class View {
expandTreeNodes(tree, expandedNodes);
}
- private static List> getExpandedNodes(JTree tree) {
+ public static List> getExpandedNodes(JTree tree) {
List> expandedNodes = new ArrayList<>();
int rowCount = tree.getRowCount();
for (int i = 0; i < rowCount; i++) {
@@ -503,7 +503,7 @@ public class View {
return expandedNodes;
}
- private static void expandTreeNodes(JTree tree, List> pathsToExpand) {
+ public static void expandTreeNodes(JTree tree, List> pathsToExpand) {
for (List pathAsStringList : pathsToExpand) {
expandTreeNode(tree, pathAsStringList);
}
diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
index 76c3da776..284958f25 100644
--- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
@@ -700,7 +700,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se
public void hilightScript(ScriptPack pack) {
TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel();
- final TreePath tp = ttm.getTagPath(pack);
+ final TreePath tp = ttm.getTreePath(pack);
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java
index bbd2e43cd..7281c93c0 100644
--- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java
@@ -835,7 +835,7 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene
@Override
public void updateSearchPos(ActionSearchResult item) {
TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel();
- TreePath tp = ttm.getTagPath(item.src);
+ TreePath tp = ttm.getTreePath(item.src);
mainPanel.tagTree.setSelectionPath(tp);
mainPanel.tagTree.scrollPathToVisible(tp);
decompiledEditor.setCaretPosition(0);
diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java
index 5381dbfca..b805d9942 100644
--- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java
+++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java
@@ -90,6 +90,11 @@ public class DumpTree extends JTree implements ActionListener {
setCellRenderer(new DumpTreeCellRenderer());
setRootVisible(false);
setBackground(Color.white);
+ setUI(new BasicTreeUI() {
+ {
+ setHashColor(Color.gray);
+ }
+ });
}
public void createContextMenu() {
@@ -281,16 +286,15 @@ public class DumpTree extends JTree implements ActionListener {
}
}
+ @Override
+ public DumpTreeModel getModel() {
+ return (DumpTreeModel) super.getModel();
+ }
+
@Override
public void setModel(TreeModel tm) {
super.setModel(tm);
- setUI(new BasicTreeUI() {
- {
- setHashColor(Color.gray);
- }
- });
-
if (tm != null) {
int rowCount = tm.getChildCount(tm.getRoot());
for (int i = rowCount - 1; i >= 0; i--) {
diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java
index 9e984d6ec..9301b5e42 100644
--- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java
+++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
@@ -34,19 +35,36 @@ import javax.swing.tree.TreePath;
*
* @author JPEXS
*/
-public class DumpTreeModel implements TreeModel {
+public final class DumpTreeModel implements TreeModel {
private final DumpInfo root;
+ private final List listeners = new ArrayList<>();
+
+ private final List swfs;
+
public DumpTreeModel(List swfs) {
- DumpInfo root = new DumpInfo("root", "", null, 0, 0);
+ this.swfs = swfs;
+ root = new DumpInfo("root", "", null, 0, 0);
+ updateSwfs();
+ }
+
+ public void updateSwfs() {
+ root.getChildInfos().clear();
for (SWFList swfList : swfs) {
for (SWF swf : swfList) {
swf.dumpInfo.name = swf.getFileTitle();
root.getChildInfos().add(swf.dumpInfo);
}
}
- this.root = root;
+
+ fireTreeStructureChanged(new TreeModelEvent(this, new TreePath(root)));
+ }
+
+ private void fireTreeStructureChanged(TreeModelEvent e) {
+ for (TreeModelListener listener : listeners) {
+ listener.treeStructureChanged(e);
+ }
}
private List searchDumpInfo(DumpInfo dumpInfo, DumpInfo parent, List path) {
@@ -126,10 +144,12 @@ public class DumpTreeModel implements TreeModel {
}
@Override
- public void addTreeModelListener(TreeModelListener tl) {
+ public void addTreeModelListener(TreeModelListener l) {
+ listeners.add(l);
}
@Override
- public void removeTreeModelListener(TreeModelListener tl) {
+ public void removeTreeModelListener(TreeModelListener l) {
+ listeners.remove(l);
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedAction.java b/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedAction.java
new file mode 100644
index 000000000..d3c7cc421
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedAction.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010-2015 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui.helpers;
+
+/**
+ *
+ * @author JPEXS
+ */
+public enum CollectionChangedAction {
+
+ ADD, REMOVE, RESET
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedEvent.java b/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedEvent.java
new file mode 100644
index 000000000..0dc5a983d
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010-2015 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui.helpers;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class CollectionChangedEvent {
+
+ private final CollectionChangedAction action;
+
+ private E oldItem = null;
+
+ private int oldIndex = -1;
+
+ private E newItem = null;
+
+ private int newIndex = -1;
+
+ public CollectionChangedEvent(CollectionChangedAction action) {
+ this(action, null, -1);
+ }
+
+ public CollectionChangedEvent(CollectionChangedAction action, E item, int index) {
+ this.action = action;
+ switch (action) {
+ case ADD:
+ newItem = item;
+ newIndex = index;
+ break;
+ case REMOVE:
+ oldItem = item;
+ oldIndex = index;
+ break;
+ }
+ }
+
+ public CollectionChangedAction getAction() {
+ return action;
+ }
+
+ public E getOldItem() {
+ return oldItem;
+ }
+
+ public int getOldIndex() {
+ return oldIndex;
+ }
+
+ public E getNewItem() {
+ return newItem;
+ }
+
+ public int getNewIndex() {
+ return newIndex;
+ }
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedListener.java b/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedListener.java
new file mode 100644
index 000000000..33b8451aa
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/helpers/CollectionChangedListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010-2015 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui.helpers;
+
+import java.util.EventListener;
+
+/**
+ *
+ * @author JPEXS
+ */
+public interface CollectionChangedListener extends EventListener {
+
+ public void collectionChanged(CollectionChangedEvent e);
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/ObservableList.java b/src/com/jpexs/decompiler/flash/gui/helpers/ObservableList.java
new file mode 100644
index 000000000..3a18795e6
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/helpers/ObservableList.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2010-2015 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui.helpers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class ObservableList implements List {
+
+ private final List list = new ArrayList<>();
+
+ private final List> listeners = new ArrayList<>();
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return list.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return list.contains(o);
+ }
+
+ @Override
+ public Iterator iterator() {
+ return list.iterator();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return list.toArray();
+ }
+
+ @Override
+ public T[] toArray(T[] a) {
+ return list.toArray(a);
+ }
+
+ @Override
+ public boolean add(E e) {
+ boolean result = list.add(e);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.ADD, e, size() - 1));
+ return result;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int idx = list.indexOf(o);
+ if (idx != -1) {
+ remove(idx);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection> c) {
+ return list.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection extends E> c) {
+ boolean result = list.addAll(c);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.RESET));
+ return result;
+ }
+
+ @Override
+ public boolean removeAll(Collection> c) {
+ boolean result = list.removeAll(c);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.RESET));
+ return result;
+ }
+
+ @Override
+ public boolean retainAll(Collection> c) {
+ boolean result = list.retainAll(c);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.RESET));
+ return result;
+ }
+
+ @Override
+ public void clear() {
+ list.clear();
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.RESET));
+ }
+
+ @Override
+ public boolean addAll(int index, Collection extends E> c) {
+ boolean result = list.addAll(index, c);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.RESET));
+ return result;
+ }
+
+ @Override
+ public E get(int index) {
+ return list.get(index);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ E result = list.set(index, element);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.RESET));
+ return result;
+ }
+
+ @Override
+ public void add(int index, E element) {
+ list.add(index, element);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.ADD, element, index));
+ }
+
+ @Override
+ public E remove(int index) {
+ E result = list.remove(index);
+ fireCollectionChanged(new CollectionChangedEvent<>(CollectionChangedAction.REMOVE, result, index));
+ return result;
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return list.indexOf(o);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return list.lastIndexOf(o);
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return list.listIterator();
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ return list.listIterator(index);
+ }
+
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ return list.subList(fromIndex, toIndex);
+ }
+
+ private void fireCollectionChanged(CollectionChangedEvent e) {
+ for (CollectionChangedListener listener : listeners) {
+ listener.collectionChanged(e);
+ }
+ }
+
+ public void addCollectionChangedListener(CollectionChangedListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeCollectionChangedListener(CollectionChangedListener listener) {
+ listeners.remove(listener);
+ }
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java
index 1c1d4c288..301ed69c2 100644
--- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java
+++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java
@@ -122,7 +122,6 @@ import javax.swing.JTree;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
@@ -217,6 +216,11 @@ public class TagTree extends JTree {
setBackground(Color.white);
setRowHeight(16);
setLargeModel(true);
+ setUI(new BasicTreeUI() {
+ {
+ setHashColor(Color.gray);
+ }
+ });
}
public void createContextMenu() {
@@ -313,7 +317,7 @@ public class TagTree extends JTree {
if (t instanceof SWFList) {
SWFList slist = (SWFList) t;
- if (slist.bundle != null) {
+ if (slist.isBundle()) {
if (slist.bundle.getClass() == ZippedSWFBundle.class) {
return TreeNodeType.BUNDLE_ZIP;
} else if (slist.bundle.getClass() == SWC.class) {
@@ -534,20 +538,7 @@ public class TagTree extends JTree {
}
@Override
- public void setModel(TreeModel tm) {
- super.setModel(tm);
-
- setUI(new BasicTreeUI() {
- {
- setHashColor(Color.gray);
- }
- });
-
- if (tm != null) {
- int rowCount = tm.getChildCount(tm.getRoot());
- for (int i = rowCount - 1; i >= 0; i--) {
- expandRow(i);
- }
- }
+ public TagTreeModel getModel() {
+ return (TagTreeModel) super.getModel();
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java
index 3a482cd47..e32dad00a 100644
--- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java
+++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java
@@ -275,7 +275,7 @@ public class TagTreeContextMenu extends JPopupMenu implements ActionListener {
} else if (item instanceof SWF) {
SWF swf = (SWF) item;
// Do not allow to close SWF in bundle
- if (swf.swfList != null && swf.swfList.bundle!=null) {
+ if (swf.swfList != null && swf.swfList.isBundle()) {
allSelectedIsSwf = false;
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java
index 5add2c69c..77054ba34 100644
--- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java
+++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java
@@ -17,11 +17,10 @@
package com.jpexs.decompiler.flash.gui.tagtree;
import com.jpexs.decompiler.flash.SWF;
-import com.jpexs.decompiler.flash.SWFContainerItem;
import com.jpexs.decompiler.flash.gui.AppStrings;
-import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.TreeNodeType;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
+import com.jpexs.decompiler.flash.gui.helpers.CollectionChangedEvent;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
@@ -46,6 +45,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
+import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
@@ -78,41 +79,67 @@ public class TagTreeModel implements TreeModel {
public static final String FOLDER_SCRIPTS = "scripts";
+ private final List listeners = new ArrayList<>();
+
private final TagTreeRoot root = new TagTreeRoot();
- private final List swfs;
+ private final List swfs;
- private final Map> swfFolders;
+ private final Map swfInfos = new WeakHashMap<>();
private final boolean addAllFolders;
- private final Map tagScriptCache;
-
public TagTreeModel(List swfs, boolean addAllFolders) {
- this.swfs = new ArrayList<>();
- this.swfFolders = new HashMap<>();
+ this.swfs = swfs;
this.addAllFolders = addAllFolders;
- this.tagScriptCache = new HashMap<>();
- Main.startWork(AppStrings.translate("work.buildingscripttree") + "...");
- for (SWFList swfList : swfs) {
- if (swfList.bundle != null) {
- this.swfs.add(swfList);
- for (SWF swf : swfList) {
- createTagList(swf);
- }
- } else {
- SWF swf = swfList.get(0);
- this.swfs.add(swf);
- createTagList(swf);
- }
- }
- Main.stopWork();
+ //Main.startWork(AppStrings.translate("work.buildingscripttree") + "...");
+ //Main.stopWork();
}
private String translate(String key) {
return AppStrings.translate(key);
}
+ public void updateSwfs(CollectionChangedEvent e) {
+ switch (e.getAction()) {
+ case ADD: {
+ TreePath rootPath = new TreePath(new Object[]{root});
+ fireTreeNodesInserted(new TreeModelEvent(this, rootPath, new int[]{e.getNewIndex()}, new Object[]{e.getNewItem()}));
+ break;
+ }
+ case REMOVE: {
+ TreePath rootPath = new TreePath(new Object[]{root});
+ fireTreeNodesRemoved(new TreeModelEvent(this, rootPath, new int[]{e.getOldIndex()}, new Object[]{e.getOldItem()}));
+ break;
+ }
+ default:
+ fireTreeStructureChanged(new TreeModelEvent(this, new TreePath(root)));
+ }
+ }
+
+ public void updateSwf(SWF swf) {
+ TreePath changedPath = getTreePath(swf == null ? getRoot() : swf);
+ fireTreeStructureChanged(new TreeModelEvent(this, changedPath));
+ }
+
+ private void fireTreeNodesRemoved(TreeModelEvent e) {
+ for (TreeModelListener listener : listeners) {
+ listener.treeNodesRemoved(e);
+ }
+ }
+
+ private void fireTreeNodesInserted(TreeModelEvent e) {
+ for (TreeModelListener listener : listeners) {
+ listener.treeNodesInserted(e);
+ }
+ }
+
+ private void fireTreeStructureChanged(TreeModelEvent e) {
+ for (TreeModelListener listener : listeners) {
+ listener.treeStructureChanged(e);
+ }
+ }
+
private List getSoundStreams(DefineSpriteTag sprite) {
List ret = new ArrayList<>();
for (Tag t : sprite.subTags) {
@@ -249,12 +276,13 @@ public class TagTreeModel implements TreeModel {
nodeList.add(otherNode);
}
+ Map currentTagScriptCache = new HashMap<>();
if (swf.isAS3()) {
if (!swf.getAbcList().isEmpty()) {
nodeList.add(new ClassesListTreeModel(swf));
}
} else {
- List subNodes = swf.getFirstLevelASMNodes(tagScriptCache);
+ List subNodes = swf.getFirstLevelASMNodes(currentTagScriptCache);
if (subNodes.size() > 0) {
TreeItem actionScriptNode = new FolderItem(translate("node.scripts"), FOLDER_SCRIPTS, swf, subNodes);
@@ -262,7 +290,10 @@ public class TagTreeModel implements TreeModel {
}
}
- swfFolders.put(swf, nodeList);
+ TagTreeSwfInfo swfInfo = new TagTreeSwfInfo();
+ swfInfo.folders = nodeList;
+ swfInfo.tagScriptCache = currentTagScriptCache;
+ swfInfos.put(swf, swfInfo);
}
public TreeItem getScriptsNode(SWF swf) {
@@ -337,7 +368,7 @@ public class TagTreeModel implements TreeModel {
return searchForFrame(swf, swf, t, frame);
}
- private List searchTag(TreeItem obj, TreeItem parent, List path) {
+ private List searchTreeItem(TreeItem obj, TreeItem parent, List path) {
List ret = null;
int cnt = getChildCount(parent);
for (int i = 0; i < cnt; i++) {
@@ -371,7 +402,7 @@ public class TagTreeModel implements TreeModel {
}
}
- ret = searchTag(obj, n, newPath);
+ ret = searchTreeItem(obj, n, newPath);
if (ret != null) {
return ret;
}
@@ -379,10 +410,10 @@ public class TagTreeModel implements TreeModel {
return ret;
}
- public TreePath getTagPath(TreeItem obj) {
+ public TreePath getTreePath(TreeItem obj) {
List path = new ArrayList<>();
path.add(getRoot());
- path = searchTag(obj, getRoot(), path);
+ path = searchTreeItem(obj, getRoot(), path);
if (path == null) {
return null;
}
@@ -396,20 +427,24 @@ public class TagTreeModel implements TreeModel {
}
private List getSwfFolders(SWF swf) {
- List ret = swfFolders.get(swf);
- if (ret == null) {
+ TagTreeSwfInfo swfInfo = swfInfos.get(swf);
+ if (swfInfo == null) {
createTagList(swf);
- ret = swfFolders.get(swf);
+ swfInfo = swfInfos.get(swf);
}
- return ret;
+ return swfInfo.folders;
}
@Override
public TreeItem getChild(Object parent, int index) {
TreeItem parentNode = (TreeItem) parent;
if (parentNode == root) {
- return swfs.get(index);
+ SWFList swfList = swfs.get(index);
+ if (!swfList.isBundle()) {
+ return swfList.get(0);
+ }
+ return swfList;
} else if (parentNode instanceof SWFList) {
return ((SWFList) parentNode).swfs.get(index);
} else if (parentNode instanceof SWF) {
@@ -435,7 +470,8 @@ public class TagTreeModel implements TreeModel {
}
if (result instanceof Tag) {
Tag resultTag = (Tag) result;
- TagScript tagScript = tagScriptCache.get(resultTag);
+ Map currentTagScriptCache = swfInfos.get(result.getSwf()).tagScriptCache;
+ TagScript tagScript = currentTagScriptCache.get(resultTag);
if (tagScript == null) {
List subNodes = new ArrayList<>();
if (result instanceof ASMSourceContainer) {
@@ -444,7 +480,7 @@ public class TagTreeModel implements TreeModel {
}
}
tagScript = new TagScript(result.getSwf(), resultTag, subNodes);
- tagScriptCache.put(resultTag, tagScript);
+ currentTagScriptCache.put(resultTag, tagScript);
}
result = tagScript;
}
@@ -511,7 +547,10 @@ public class TagTreeModel implements TreeModel {
TreeItem parentNode = (TreeItem) parent;
TreeItem childNode = (TreeItem) child;
if (parentNode == root) {
- return swfs.indexOf(childNode);
+ SWFList swfList = child instanceof SWFList
+ ? (SWFList) child
+ : ((SWF) child).swfList;
+ return swfs.indexOf(swfList);
} else if (parentNode instanceof SWFList) {
return ((SWFList) parentNode).swfs.indexOf(childNode);
} else if (parentNode instanceof SWF) {
@@ -550,9 +589,11 @@ public class TagTreeModel implements TreeModel {
@Override
public void addTreeModelListener(TreeModelListener l) {
+ listeners.add(l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
+ listeners.remove(l);
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeSwfInfo.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeSwfInfo.java
new file mode 100644
index 000000000..5d95f5314
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeSwfInfo.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010-2015 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.jpexs.decompiler.flash.gui.tagtree;
+
+import com.jpexs.decompiler.flash.tags.Tag;
+import com.jpexs.decompiler.flash.timeline.TagScript;
+import com.jpexs.decompiler.flash.treeitems.TreeItem;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class TagTreeSwfInfo {
+
+ public List folders;
+
+ public Map tagScriptCache;
+}