do not recreate tree model every time

This commit is contained in:
honfika@gmail.com
2015-03-07 14:38:26 +01:00
parent 99ec0a592c
commit 3c995f42e3
21 changed files with 625 additions and 145 deletions

View File

@@ -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();

View File

@@ -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}.
* <p>
* 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<String, LinkedList<RegistryEntry>> codecMap;
private HashMap<String, LinkedList<RegistryEntry>> readerMap;
private HashMap<String, LinkedList<RegistryEntry>> writerMap;
private HashMap<String, Format> 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<String, LinkedList<RegistryEntry>> i:codecMap.entrySet()) {
LinkedList<RegistryEntry> ll=i.getValue();
for (Iterator<RegistryEntry> j=ll.iterator();j.hasNext();) {
RegistryEntry e=j.next();
for (Map.Entry<String, LinkedList<RegistryEntry>> i : codecMap.entrySet()) {
LinkedList<RegistryEntry> ll = i.getValue();
for (Iterator<RegistryEntry> j = ll.iterator(); j.hasNext();) {
RegistryEntry e = j.next();
if (e.className.equals(codecClass)) {
j.remove();
}
}
}
}
}

View File

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

View File

@@ -34,16 +34,16 @@ public class SWFList implements List<SWF>, SWFContainerItem {
public String name;
//public boolean isBundle;
public SWFBundle bundle;
//public Class bundleClass;
public SWFSourceInfo sourceInfo;
public List<SWF> 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<SWF>, SWFContainerItem {
@Override
public String toString() {
if (bundle != null) {
if (isBundle()) {
return name;
} else {
return swfs.get(0).getFileTitle();

View File

@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.treeitems;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFBundle;
/**
*

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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<SWFList> swfs;
private final ObservableList<SWFList> 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<List<String>> 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<List<String>> 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();

View File

@@ -483,7 +483,7 @@ public class View {
expandTreeNodes(tree, expandedNodes);
}
private static List<List<String>> getExpandedNodes(JTree tree) {
public static List<List<String>> getExpandedNodes(JTree tree) {
List<List<String>> 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<List<String>> pathsToExpand) {
public static void expandTreeNodes(JTree tree, List<List<String>> pathsToExpand) {
for (List<String> pathAsStringList : pathsToExpand) {
expandTreeNode(tree, pathAsStringList);
}

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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--) {

View File

@@ -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<TreeModelListener> listeners = new ArrayList<>();
private final List<SWFList> swfs;
public DumpTreeModel(List<SWFList> 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<DumpInfo> searchDumpInfo(DumpInfo dumpInfo, DumpInfo parent, List<DumpInfo> 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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.helpers;
/**
*
* @author JPEXS
*/
public enum CollectionChangedAction {
ADD, REMOVE, RESET
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.helpers;
/**
*
* @author JPEXS
*/
public class CollectionChangedEvent<E> {
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;
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.helpers;
import java.util.EventListener;
/**
*
* @author JPEXS
*/
public interface CollectionChangedListener<E> extends EventListener {
public void collectionChanged(CollectionChangedEvent<E> e);
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<E> implements List<E> {
private final List<E> list = new ArrayList<>();
private final List<CollectionChangedListener<E>> 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<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> 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<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
private void fireCollectionChanged(CollectionChangedEvent<E> e) {
for (CollectionChangedListener<E> listener : listeners) {
listener.collectionChanged(e);
}
}
public void addCollectionChangedListener(CollectionChangedListener<E> listener) {
listeners.add(listener);
}
public void removeCollectionChangedListener(CollectionChangedListener<E> listener) {
listeners.remove(listener);
}
}

View File

@@ -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();
}
}

View File

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

View File

@@ -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<TreeModelListener> listeners = new ArrayList<>();
private final TagTreeRoot root = new TagTreeRoot();
private final List<SWFContainerItem> swfs;
private final List<SWFList> swfs;
private final Map<SWF, List<TreeItem>> swfFolders;
private final Map<SWF, TagTreeSwfInfo> swfInfos = new WeakHashMap<>();
private final boolean addAllFolders;
private final Map<Tag, TagScript> tagScriptCache;
public TagTreeModel(List<SWFList> 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<SoundStreamHeadTypeTag> getSoundStreams(DefineSpriteTag sprite) {
List<SoundStreamHeadTypeTag> ret = new ArrayList<>();
for (Tag t : sprite.subTags) {
@@ -249,12 +276,13 @@ public class TagTreeModel implements TreeModel {
nodeList.add(otherNode);
}
Map<Tag, TagScript> currentTagScriptCache = new HashMap<>();
if (swf.isAS3()) {
if (!swf.getAbcList().isEmpty()) {
nodeList.add(new ClassesListTreeModel(swf));
}
} else {
List<TreeItem> subNodes = swf.getFirstLevelASMNodes(tagScriptCache);
List<TreeItem> 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<TreeItem> searchTag(TreeItem obj, TreeItem parent, List<TreeItem> path) {
private List<TreeItem> searchTreeItem(TreeItem obj, TreeItem parent, List<TreeItem> path) {
List<TreeItem> 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<TreeItem> 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<TreeItem> getSwfFolders(SWF swf) {
List<TreeItem> 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<Tag, TagScript> currentTagScriptCache = swfInfos.get(result.getSwf()).tagScriptCache;
TagScript tagScript = currentTagScriptCache.get(resultTag);
if (tagScript == null) {
List<TreeItem> 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);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<TreeItem> folders;
public Map<Tag, TagScript> tagScriptCache;
}