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