dumpview: allow opening multiple swfs, context menu: expand all and close menu items

show abc and actionbytes in dump view, hexview style fixes
better scroll to view mode in hex editor
This commit is contained in:
honfika
2014-06-28 07:31:28 +02:00
parent 1bed823af5
commit cb7baba8e9
112 changed files with 3473 additions and 3011 deletions
+26 -26
View File
@@ -27,7 +27,6 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
*
@@ -41,6 +40,8 @@ public class HexView extends JTable {
private byte[] data;
private final String[] highlightColorsStr = new String[]{/*"EEEEEE", */"29AEC2", "9AC88C", "DF5F80", "EEA32E", "FFD200", "5E9B4C", "D3E976", "A3AEC2"};
private final Color[] highlightColors;
private Color bgColor = Color.decode("#F7F7F7");
private Color bgColorAlternate = Color.decode("#EDEDED");
public class HighlightCellRenderer extends DefaultTableCellRenderer {
@@ -48,9 +49,9 @@ public class HexView extends JTable {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
if (highlightStarts != null) {
int level = -1;
if (col > 0 && highlightStarts != null) {
int idx = row * bytesInRow + ((col > bytesInRow) ? (col - bytesInRow - 1) : (col - 1));
int level = -1;
for (int i = 0; i < highlightStarts.length; i++) {
if (highlightStarts[i] <= idx && highlightEnds[i] >= idx) {
level++;
@@ -58,12 +59,14 @@ public class HexView extends JTable {
break;
}
}
if (level > -1) {
l.setBackground(highlightColors[level % highlightColors.length]);
} else {
l.setBackground(Color.white);
}
}
if (level > -1) {
l.setBackground(highlightColors[level % highlightColors.length]);
} else {
l.setBackground(row % 2 == 0 ? bgColor : bgColorAlternate);
}
return l;
}
}
@@ -131,17 +134,20 @@ public class HexView extends JTable {
setShowHorizontalLines(false);
setShowVerticalLines(false);
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
HighlightCellRenderer cellRenderer = new HighlightCellRenderer();
TableColumnModel columnModel = getColumnModel();
columnModel.getColumn(0).setMaxWidth(80);
TableColumn column = columnModel.getColumn(0);
column.setMaxWidth(80);
//column.setCellRenderer(cellRenderer);
for (int i = 0; i < bytesInRow; i++) {
TableColumn column = columnModel.getColumn(i + 1);
column = columnModel.getColumn(i + 1);
column.setMaxWidth(25);
column.setCellRenderer(cellRenderer);
}
for (int i = 0; i < bytesInRow; i++) {
TableColumn column = columnModel.getColumn(i + bytesInRow + 1);
column = columnModel.getColumn(i + bytesInRow + 1);
column.setMaxWidth(10);
column.setCellRenderer(cellRenderer);
}
@@ -163,24 +169,18 @@ public class HexView extends JTable {
}
public void scrollToByte(long byteNum) {
// HACK to scroll current selection to visible
int row = (int) (byteNum / bytesInRow);
final int pageSize = (int) (getParent().getSize().getHeight() / getRowHeight());
int byteCount = data.length;
int rowCount = byteCount / bytesInRow;
if (byteCount % bytesInRow != 0) {
rowCount++;
}
int row2 = Math.min(row + pageSize - 2, rowCount - 1);
getSelectionModel().setSelectionInterval(row2, row2);
scrollRectToVisible(new Rectangle(getCellRect(row2, 0, true)));
//final int pageSize = (int) (getParent().getSize().getHeight() / getRowHeight());
getSelectionModel().setSelectionInterval(row, row);
scrollRectToVisible(new Rectangle(getCellRect(row, 0, true)));
// END HACK
}
public void scrollToByte(long[] byteNumStarts, long[] byteNumEnds) {
for (int i = 0; i < byteNumStarts.length; i++) {
scrollToByte(byteNumStarts[i]);
scrollToByte(byteNumEnds[i]);
scrollToByte(byteNumStarts[i]);
}
}
}
@@ -357,12 +357,14 @@ public class MainFrameClassicMenu implements MainFrameMenu, ActionListener {
deobfuscationCommandButton.setEnabled(hasAbc);*/
}
private void saveAs(SWF swf, SaveFileMode mode) {
private boolean saveAs(SWF swf, SaveFileMode mode) {
if (Main.saveFileDialog(swf, mode)) {
swf.fileTitle = null;
mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : ""));
saveCommandButton.setEnabled(mainFrame.panel.getCurrentSwf() != null);
return true;
}
return false;
}
@Override
@@ -481,17 +483,19 @@ public class MainFrameClassicMenu implements MainFrameMenu, ActionListener {
case ACTION_SAVE: {
SWF swf = mainFrame.panel.getCurrentSwf();
SWFNode snode = ((TagTreeModel) mainFrame.panel.tagTree.getModel()).getSwfNode(swf);
boolean saved = false;
if (snode.binaryData != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
swf.saveTo(baos);
snode.binaryData.binaryData = baos.toByteArray();
snode.binaryData.setModified(true);
saved = true;
} catch (IOException ex) {
Logger.getLogger(MainFrameRibbonMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex);
}
} else if (swf.file == null) {
saveAs(swf, SaveFileMode.SAVEAS);
saved = saveAs(swf, SaveFileMode.SAVEAS);
} else {
try {
Main.saveFile(swf, swf.file);
@@ -500,13 +504,16 @@ public class MainFrameClassicMenu implements MainFrameMenu, ActionListener {
View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
swf.clearModified();
if (saved) {
swf.clearModified();
}
}
break;
case ACTION_SAVE_AS: {
SWF swf = mainFrame.panel.getCurrentSwf();
saveAs(swf, SaveFileMode.SAVEAS);
swf.clearModified();
if (saveAs(swf, SaveFileMode.SAVEAS)) {
swf.clearModified();
}
}
break;
case ACTION_SAVE_AS_EXE: {
@@ -538,12 +538,14 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
deobfuscationCommandButton.setEnabled(hasAbc);
}
private void saveAs(SWF swf, SaveFileMode mode) {
private boolean saveAs(SWF swf, SaveFileMode mode) {
if (Main.saveFileDialog(swf, mode)) {
swf.fileTitle = null;
mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : ""));
saveCommandButton.setEnabled(mainFrame.panel.getCurrentSwf() != null);
return true;
}
return false;
}
@Override
@@ -672,32 +674,38 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
case ACTION_SAVE: {
SWF swf = mainFrame.panel.getCurrentSwf();
SWFNode snode = ((TagTreeModel) mainFrame.panel.tagTree.getModel()).getSwfNode(swf);
boolean saved = false;
if (snode.binaryData != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
swf.saveTo(baos);
snode.binaryData.binaryData = baos.toByteArray();
snode.binaryData.setModified(true);
saved = true;
} catch (IOException ex) {
Logger.getLogger(MainFrameRibbonMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex);
}
} else if (swf.file == null) {
saveAs(swf, SaveFileMode.SAVEAS);
saved = saveAs(swf, SaveFileMode.SAVEAS);
} else {
try {
Main.saveFile(swf, swf.file);
saved = true;
} catch (IOException ex) {
Logger.getLogger(MainFrameRibbonMenu.class.getName()).log(Level.SEVERE, null, ex);
View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
swf.clearModified();
if (saved) {
swf.clearModified();
}
}
break;
case ACTION_SAVE_AS: {
SWF swf = mainFrame.panel.getCurrentSwf();
saveAs(swf, SaveFileMode.SAVEAS);
swf.clearModified();
if (saveAs(swf, SaveFileMode.SAVEAS)) {
swf.clearModified();
}
}
break;
case ACTION_SAVE_AS_EXE: {
+40 -351
View File
@@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode;
import com.jpexs.decompiler.flash.exporters.BinaryDataExporter;
import com.jpexs.decompiler.flash.exporters.FontExporter;
import com.jpexs.decompiler.flash.exporters.ImageExporter;
@@ -59,6 +60,9 @@ import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog;
import com.jpexs.decompiler.flash.gui.abc.treenodes.TreeElement;
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.player.FlashPlayerPanel;
import com.jpexs.decompiler.flash.gui.timeline.TimelineFrame;
import com.jpexs.decompiler.flash.gui.treenodes.SWFBundleNode;
@@ -96,7 +100,6 @@ import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.Container;
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
@@ -182,17 +185,13 @@ import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
@@ -204,7 +203,6 @@ import javax.swing.filechooser.FileFilter;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
*
@@ -247,6 +245,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
private final PreviewPanel previewPanel;
private DumpViewPanel dumpViewPanel;
private final JPanel treePanel;
private TreePanelMode treePanelMode;
private AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler();
private CancellableWorker setSourceWorker;
public TreeNode oldNode;
@@ -255,12 +254,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
public static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR";
public static final String ACTION_REPLACE = "REPLACE";
private static final String ACTION_RAW_EDIT = "RAWEDIT";
private static final String ACTION_JUMP_TO_CHARACTER = "JUMPTOCHARACTER";
private static final String ACTION_REMOVE_ITEM = "REMOVEITEM";
private static final String ACTION_REMOVE_ITEM_WITH_DEPENDENCIES = "REMOVEITEMWITHDEPENDENCIES";
private static final String ACTION_CLOSE_SWF = "CLOSESWF";
private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE";
// play morph shape in 2 second(s)
public static final int MORPH_SHAPE_ANIMATION_LENGTH = 2;
@@ -311,146 +304,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
statusPanel.setWorkStatus(s, worker);
}
private void createContextMenu() {
final JPopupMenu contextPopupMenu = new JPopupMenu();
final JMenuItem expandRecursiveMenuItem = new JMenuItem(translate("contextmenu.expandAll"));
expandRecursiveMenuItem.addActionListener(this);
expandRecursiveMenuItem.setActionCommand(ACTION_EXPAND_RECURSIVE);
contextPopupMenu.add(expandRecursiveMenuItem);
final JMenuItem removeMenuItem = new JMenuItem(translate("contextmenu.remove"));
removeMenuItem.addActionListener(this);
removeMenuItem.setActionCommand(ACTION_REMOVE_ITEM);
contextPopupMenu.add(removeMenuItem);
final JMenuItem removeWithDependenciesMenuItem = new JMenuItem(translate("contextmenu.removeWithDependencies"));
removeWithDependenciesMenuItem.addActionListener(this);
removeWithDependenciesMenuItem.setActionCommand(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
contextPopupMenu.add(removeWithDependenciesMenuItem);
final JMenuItem exportSelectionMenuItem = new JMenuItem(translate("menu.file.export.selection"));
exportSelectionMenuItem.setActionCommand(MainFrameRibbonMenu.ACTION_EXPORT_SEL);
exportSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(exportSelectionMenuItem);
final JMenuItem replaceSelectionMenuItem = new JMenuItem(translate("button.replace"));
replaceSelectionMenuItem.setActionCommand(ACTION_REPLACE);
replaceSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(replaceSelectionMenuItem);
final JMenuItem rawEditMenuItem = new JMenuItem(translate("contextmenu.rawEdit"));
rawEditMenuItem.setActionCommand(ACTION_RAW_EDIT);
rawEditMenuItem.addActionListener(this);
rawEditMenuItem.setVisible(false);
contextPopupMenu.add(rawEditMenuItem);
final JMenuItem jumpToCharacterMenuItem = new JMenuItem(translate("contextmenu.jumpToCharacter"));
jumpToCharacterMenuItem.setActionCommand(ACTION_JUMP_TO_CHARACTER);
jumpToCharacterMenuItem.addActionListener(this);
jumpToCharacterMenuItem.setVisible(false);
contextPopupMenu.add(jumpToCharacterMenuItem);
final JMenuItem closeSelectionMenuItem = new JMenuItem(translate("contextmenu.closeSwf"));
closeSelectionMenuItem.setActionCommand(ACTION_CLOSE_SWF);
closeSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(closeSelectionMenuItem);
final JMenu moveTagMenu = new JMenu(translate("contextmenu.moveTag"));
contextPopupMenu.add(moveTagMenu);
tagTree.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int row = tagTree.getClosestRowForLocation(e.getX(), e.getY());
int[] selectionRows = tagTree.getSelectionRows();
if (!Helper.contains(selectionRows, row)) {
tagTree.setSelectionRow(row);
}
TreePath[] paths = tagTree.getSelectionPaths();
if (paths == null || paths.length == 0) {
return;
}
boolean allSelectedIsTagOrFrame = true;
for (TreePath treePath : paths) {
TreeNode treeNode = (TreeNode) treePath.getLastPathComponent();
TreeItem tag = treeNode.getItem();
if (!(tag instanceof Tag) && !(tag instanceof FrameNodeItem)) {
allSelectedIsTagOrFrame = false;
break;
}
}
replaceSelectionMenuItem.setVisible(false);
closeSelectionMenuItem.setVisible(false);
moveTagMenu.setVisible(false);
expandRecursiveMenuItem.setVisible(false);
if (paths.length == 1) {
TreeNode treeNode = (TreeNode) paths[0].getLastPathComponent();
TreeItem item = ((TreeNode) treeNode).getItem();
if (item instanceof ImageTag && ((ImageTag) item).importSupported()) {
replaceSelectionMenuItem.setVisible(true);
}
if (item instanceof DefineBinaryDataTag) {
replaceSelectionMenuItem.setVisible(true);
}
if (item instanceof DefineSoundTag) {
replaceSelectionMenuItem.setVisible(true);
}
if (treeNode instanceof SWFNode) {
closeSelectionMenuItem.setVisible(true);
}
if (item instanceof Tag && swfs.size() > 1) {
final Tag tag = (Tag) item;
moveTagMenu.removeAll();
for (SWFList targetSwfList : swfs) {
for (final SWF targetSwf : targetSwfList) {
if (targetSwf != tag.getSwf()) {
JMenuItem swfItem = new JMenuItem(targetSwf.getShortFileName());
swfItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
tag.getSwf().tags.remove(tag);
tag.setSwf(targetSwf);
targetSwf.tags.add(tag);
refreshTree();
}
});
moveTagMenu.add(swfItem);
}
}
}
moveTagMenu.setVisible(true);
}
TreeModel model = tagTree.getModel();
expandRecursiveMenuItem.setVisible(model.getChildCount(treeNode) > 0);
jumpToCharacterMenuItem.setVisible(item instanceof CharacterIdTag && !(item instanceof CharacterTag));
rawEditMenuItem.setVisible(item instanceof Tag);
}
removeMenuItem.setVisible(allSelectedIsTagOrFrame);
exportSelectionMenuItem.setEnabled(hasExportableNodes());
contextPopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
private JPanel createWelcomePanel() {
JPanel welcomePanel = new JPanel();
welcomePanel.setLayout(new BoxLayout(welcomePanel, BoxLayout.Y_AXIS));
@@ -530,7 +383,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
cl2.show(detailPanel, DETAILCARDEMPTYPANEL);
UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName());
tagTree = new TagTree((TagTreeModel) null);
tagTree = new TagTree((TagTreeModel) null, this);
tagTree.addTreeSelectionListener(this);
DragSource dragSource = DragSource.getDefaultDragSource();
@@ -612,10 +465,11 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
});
createContextMenu();
tagTree.createContextMenu(swfs);
dumpTree = new DumpTree((DumpTreeModel) null);
dumpTree = new DumpTree((DumpTreeModel) null, this);
dumpTree.addTreeSelectionListener(this);
dumpTree.createContextMenu();
statusPanel = new MainFrameStatusPanel(this);
add(statusPanel, BorderLayout.SOUTH);
@@ -1034,19 +888,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
}
public List<TagNode> getSelectedNodes() {
List<TagNode> ret = new ArrayList<>();
TreePath[] tps = tagTree.getSelectionPaths();
if (tps == null) {
return ret;
}
for (TreePath tp : tps) {
TagNode te = (TagNode) tp.getLastPathComponent();
ret.add(te);
}
return ret;
}
public void renameIdentifier(SWF swf, String identifier) throws InterruptedException {
String oldName = identifier;
String newName = View.showInputDialog(translate("rename.enternew"), oldName);
@@ -1094,48 +935,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
}
public List<TreeNode> getSelected(JTree tree) {
TreeSelectionModel tsm = tree.getSelectionModel();
TreePath[] tps = tsm.getSelectionPaths();
List<TreeNode> ret = new ArrayList<>();
if (tps == null) {
return ret;
}
for (TreePath tp : tps) {
TreeNode treeNode = (TreeNode) tp.getLastPathComponent();
ret.add(treeNode);
}
return ret;
}
public List<TreeNode> getAllSubs(JTree tree, TreeNode o) {
TagTreeModel tm = (TagTreeModel) tree.getModel();
List<TreeNode> ret = new ArrayList<>();
for (int i = 0; i < tm.getChildCount(o); i++) {
TreeNode c = tm.getChild(o, i);
ret.add(c);
ret.addAll(getAllSubs(tree, c));
}
return ret;
}
public List<TreeNode> getAllSelected(TagTree tree) {
TreeSelectionModel tsm = tree.getSelectionModel();
TreePath[] tps = tsm.getSelectionPaths();
List<TreeNode> ret = new ArrayList<>();
if (tps == null) {
return ret;
}
for (TreePath tp : tps) {
TreeNode treeNode = (TreeNode) tp.getLastPathComponent();
ret.add(treeNode);
ret.addAll(getAllSubs(tree, treeNode));
}
return ret;
}
public List<TreeNode> getASTreeNodes(TagTree tree) {
List<TreeNode> result = new ArrayList<>();
TagTreeModel tm = (TagTreeModel) tree.getModel();
@@ -1165,68 +964,10 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
private SearchDialog searchDialog;
public boolean hasExportableNodes() {
return !getSelection(getCurrentSwf()).isEmpty();
}
private List<Object> getSelection(SWF swf) {
List<Object> ret = new ArrayList<>();
List<TreeNode> sel = getAllSelected(tagTree);
for (TreeNode d : sel) {
if (d.getItem().getSwf() != swf) {
continue;
}
if (d instanceof ContainerNode) {
ContainerNode n = (ContainerNode) d;
TreeNodeType nodeType = TagTree.getTreeNodeType(n.getItem());
if (nodeType == TreeNodeType.IMAGE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.SHAPE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.MORPH_SHAPE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.AS) {
ret.add(n);
}
if (nodeType == TreeNodeType.MOVIE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.SOUND) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.BINARY_DATA) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.TEXT) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.FONT) {
ret.add((Tag) n.getItem());
}
}
if (d instanceof FrameNode) {
FrameNode fn = (FrameNode) d;
if (!fn.scriptsNode) {
ret.add(d.getItem());
}
}
if (d instanceof TreeElement) {
if (((TreeElement) d).isLeaf()) {
TreeElement treeElement = (TreeElement) d;
ret.add((ScriptPack) treeElement.getItem());
}
}
}
return ret;
}
public List<File> exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException {
List<File> ret = new ArrayList<>();
List<TreeNode> sel = getAllSelected(tagTree);
List<TreeNode> sel = tagTree.getAllSelected(tagTree);
for (SWFList swfList : swfs) {
for (SWF swf : swfList) {
@@ -1371,16 +1112,24 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
return null;
}
TreeNode treeNode = (TreeNode) tagTree.getLastSelectedPathComponent();
if (treeNode == null) {
return swfs.get(0).get(0);
}
if (treePanelMode == TreePanelMode.TAG_TREE) {
TreeNode treeNode = (TreeNode) tagTree.getLastSelectedPathComponent();
if (treeNode == null) {
return swfs.get(0).get(0);
}
if (treeNode instanceof SWFBundleNode) {
return null;
}
if (treeNode instanceof SWFBundleNode) {
return null;
}
return treeNode.getItem().getSwf();
return treeNode.getItem().getSwf();
} else if (treePanelMode == TreePanelMode.DUMP_TREE) {
DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent();
return DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf();
}
return null;
}
private void clearCache() {
@@ -1849,7 +1598,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
public void export(final boolean onlySel) {
final SWF swf = getCurrentSwf();
List<Object> sel = getSelection(swf);
List<Object> sel = tagTree.getSelection(swf);
if (!onlySel) {
sel = null;
} else {
@@ -2085,6 +1834,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
showCard(CARDEMPTYPANEL);
TreeItem treeItem = tagTree.getCurrentTreeItem();
View.refreshTree(tagTree, new TagTreeModel(mainFrame, swfs));
View.refreshTree(dumpTree, new DumpTreeModel(swfs));
if (treeItem != null) {
setTreeItem(treeItem);
}
@@ -2238,7 +1988,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
try {
SWF swf = it.getSwf();
if (it instanceof DefineBitsTag) {
DefineBitsJPEG2Tag jpeg2Tag = new DefineBitsJPEG2Tag(swf, it.getPos(), it.getOriginalLength(), it.getCharacterId(), data);
DefineBitsJPEG2Tag jpeg2Tag = new DefineBitsJPEG2Tag(swf, it.getOriginalRange(), it.getCharacterId(), data);
jpeg2Tag.setModified(true);
swf.tags.set(swf.tags.indexOf(it), jpeg2Tag);
swf.updateCharacters();
@@ -2274,74 +2024,6 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
}
break;
case ACTION_RAW_EDIT: {
TreeItem item = tagTree.getCurrentTreeItem();
if (item == null) {
return;
}
showCard(CARDPREVIEWPANEL);
previewPanel.showGenericTagPanel((Tag) item);
}
break;
case ACTION_JUMP_TO_CHARACTER: {
TreeItem item = tagTree.getCurrentTreeItem();
if (item == null || !(item instanceof CharacterIdTag)) {
return;
}
CharacterIdTag characterIdTag = (CharacterIdTag) item;
setTreeItem(item.getSwf().characters.get(characterIdTag.getCharacterId()));
}
break;
case ACTION_EXPAND_RECURSIVE: {
TreePath path = tagTree.getSelectionPath();
if (path == null) {
return;
}
View.expandTreeNodesRecursive(tagTree, path, true);
}
break;
case ACTION_REMOVE_ITEM:
case ACTION_REMOVE_ITEM_WITH_DEPENDENCIES:
List<TreeNode> sel = getSelected(tagTree);
List<Tag> tagsToRemove = new ArrayList<>();
for (TreeNode o : sel) {
TreeItem tag = o.getItem();
if (tag instanceof Tag) {
tagsToRemove.add((Tag) tag);
} else if (tag instanceof FrameNodeItem) {
FrameNodeItem frameNode = (FrameNodeItem) tag;
Frame frame = frameNode.getParent().getTimeline().frames.get(frameNode.getFrame() - 1);
if (frame.showFrameTag != null) {
tagsToRemove.add(frame.showFrameTag);
} else {
// this should be the last frame, so remove the inner tags
tagsToRemove.addAll(frame.innerTags);
}
}
}
boolean removeDependencies = e.getActionCommand().equals(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
if (tagsToRemove.size() == 1) {
Tag tag = tagsToRemove.get(0);
if (View.showConfirmDialog(this, translate("message.confirm.remove").replace("%item%", tag.toString()), translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
tag.getSwf().removeTag(tag, removeDependencies);
refreshTree();
}
} else if (tagsToRemove.size() > 1) {
if (View.showConfirmDialog(this, translate("message.confirm.removemultiple").replace("%count%", Integer.toString(tagsToRemove.size())), translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
for (Tag tag : tagsToRemove) {
tag.getSwf().removeTag(tag, removeDependencies);
}
refreshTree();
}
}
break;
case ACTION_CLOSE_SWF: {
Main.closeFile(getCurrentSwfList());
}
}
if (Main.isWorking()) {
return;
@@ -2382,8 +2064,8 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
private void dumpTreeValueChanged(TreeSelectionEvent e) {
DumpInfo dumpInfo = (DumpInfo) e.getPath().getLastPathComponent();
// todo honfika: support multiple swf
dumpViewPanel.setData(swfs.get(0).swfs.get(0).uncompressedData, dumpInfo);
dumpViewPanel.setData(DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().uncompressedData, dumpInfo);
dumpViewPanel.revalidate();
showCard(CARDDUMPVIEW);
}
@@ -2438,8 +2120,10 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
treePanel.removeAll();
if (show) {
treePanel.add(new JScrollPane(dumpTree), BorderLayout.CENTER);
treePanelMode = TreePanelMode.DUMP_TREE;
} else {
treePanel.add(new JScrollPane(tagTree), BorderLayout.CENTER);
treePanelMode = TreePanelMode.TAG_TREE;
}
treePanel.revalidate();
}
@@ -2619,13 +2303,18 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
previewPanel.setParametersPanelVisible(false);
}
} else if (tagObj instanceof Tag) {
showCard(CARDPREVIEWPANEL);
previewPanel.showGenericTagPanel((Tag) tagObj);
showGenericTag((Tag) tagObj);
} else {
showCard(CARDEMPTYPANEL);
}
}
public void showGenericTag(Tag tag) {
showCard(CARDPREVIEWPANEL);
previewPanel.showGenericTagPanel(tag);
}
private void showFontTag(FontTag ft) {
previewPanel.showFontPanel(ft);
@@ -683,8 +683,8 @@ public class PreviewPanel extends JSplitPane implements ActionListener {
List<Action> actions;
DoActionTag doa;
doa = new DoActionTag(swf, 0, 0);
actions = ASMParser.parse(0, 0, false,
doa = new DoActionTag(swf, null);
actions = ASMParser.parse(0, false,
"ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n"
+ "Push \"_root\"\n"
+ "GetVariable\n"
@@ -703,7 +703,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener {
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
actions = ASMParser.parse(0, 0, false,
actions = ASMParser.parse(0, false,
"ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"start\"\n"
+ "StopSounds\n"
+ "Push \"_root\"\n"
@@ -730,7 +730,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener {
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
actions = ASMParser.parse(0, 0, false,
actions = ASMParser.parse(0, false,
"ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"onSoundComplete\" \"start\" \"execParam\"\n"
+ "StopSounds\n"
+ "Push \"_root\"\n"
@@ -774,7 +774,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener {
doa.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
actions = ASMParser.parse(0, 0, false,
actions = ASMParser.parse(0, false,
"StopSounds\n"
+ "Stop", swf.version, false);
doa.setActions(actions);
+614 -304
View File
@@ -1,304 +1,614 @@
/*
* Copyright (C) 2010-2014 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;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.gui.treenodes.TagTreeRoot;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.DefineFont3Tag;
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineFontTag;
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag;
import com.jpexs.decompiler.flash.tags.DefineShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineShape3Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineShapeTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.decompiler.flash.treeitems.StringItem;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultTreeCellRenderer;
/**
*
* @author JPEXS
*/
public class TagTree extends JTree {
public class TagTreeCellRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
TreeNode treeNode = (TreeNode) value;
TreeItem val = treeNode.getItem();
TreeNodeType type = getTreeNodeType(val);
if (type != null) {
if (type == TreeNodeType.FOLDER && expanded) {
type = TreeNodeType.FOLDER_OPEN;
}
String itemName = type.toString();
if (type == TreeNodeType.FOLDER || type == TreeNodeType.FOLDER_OPEN) {
if (val instanceof StringItem) {
StringItem si = (StringItem) val;
if (!TagTreeRoot.FOLDER_ROOT.equals(si.getName())) {
itemName = "folder" + si.getName();
}
}
}
String tagTypeStr = itemName.toLowerCase().replace("_", "");
setIcon(View.getIcon(tagTypeStr + "16"));
}
Font font = getFont();
boolean isModified = false;
if (treeNode instanceof TreeNode) {
if (treeNode.getItem() instanceof Tag) {
Tag tag = (Tag) treeNode.getItem();
if (tag.isModified()) {
isModified = true;
}
}
}
if (isModified) {
font = font.deriveFont(Font.BOLD);
} else {
font = font.deriveFont(Font.PLAIN);
}
setFont(font);
setUI(new BasicLabelUI());
setOpaque(false);
//setBackground(Color.green);
setBackgroundNonSelectionColor(Color.white);
//setBackgroundSelectionColor(Color.ORANGE);
return this;
}
}
TagTree(TagTreeModel treeModel) {
super(treeModel);
setCellRenderer(new TagTreeCellRenderer());
setRootVisible(false);
setBackground(Color.white);
setUI(new BasicTreeUI() {
@Override
public void paint(Graphics g, JComponent c) {
setHashColor(Color.gray);
super.paint(g, c);
}
});
}
public static TreeNodeType getTreeNodeType(TreeItem t) {
if ((t instanceof DefineFontTag)
|| (t instanceof DefineFont2Tag)
|| (t instanceof DefineFont3Tag)
|| (t instanceof DefineFont4Tag)
|| (t instanceof DefineCompactedFont)) {
return TreeNodeType.FONT;
}
if ((t instanceof DefineTextTag)
|| (t instanceof DefineText2Tag)
|| (t instanceof DefineEditTextTag)) {
return TreeNodeType.TEXT;
}
if ((t instanceof DefineBitsTag)
|| (t instanceof DefineBitsJPEG2Tag)
|| (t instanceof DefineBitsJPEG3Tag)
|| (t instanceof DefineBitsJPEG4Tag)
|| (t instanceof DefineBitsLosslessTag)
|| (t instanceof DefineBitsLossless2Tag)) {
return TreeNodeType.IMAGE;
}
if ((t instanceof DefineShapeTag)
|| (t instanceof DefineShape2Tag)
|| (t instanceof DefineShape3Tag)
|| (t instanceof DefineShape4Tag)) {
return TreeNodeType.SHAPE;
}
if ((t instanceof DefineMorphShapeTag) || (t instanceof DefineMorphShape2Tag)) {
return TreeNodeType.MORPH_SHAPE;
}
if (t instanceof DefineSpriteTag) {
return TreeNodeType.SPRITE;
}
if ((t instanceof DefineButtonTag) || (t instanceof DefineButton2Tag)) {
return TreeNodeType.BUTTON;
}
if (t instanceof ASMSource) {
return TreeNodeType.AS;
}
if (t instanceof ScriptPack) {
return TreeNodeType.AS;
}
if (t instanceof AS2PackageNodeItem) {
return TreeNodeType.PACKAGE;
}
if (t instanceof AS3PackageNodeItem) {
return TreeNodeType.PACKAGE;
}
if (t instanceof FrameNodeItem) {
return TreeNodeType.FRAME;
}
if (t instanceof ShowFrameTag) {
return TreeNodeType.SHOW_FRAME;
}
if (t instanceof DefineVideoStreamTag) {
return TreeNodeType.MOVIE;
}
if ((t instanceof DefineSoundTag) || (t instanceof SoundStreamHeadTag) || (t instanceof SoundStreamHead2Tag)) {
return TreeNodeType.SOUND;
}
if (t instanceof DefineBinaryDataTag) {
return TreeNodeType.BINARY_DATA;
}
if (t instanceof SWF) {
return TreeNodeType.FLASH;
}
if (t instanceof SWFList) {
SWFList slist = (SWFList) t;
if (slist.name != null) {
if (slist.name.toLowerCase().endsWith(".zip")) {
return TreeNodeType.BUNDLE_ZIP;
}
if (slist.name.toLowerCase().endsWith(".swc")) {
return TreeNodeType.BUNDLE_SWC;
} else {
return TreeNodeType.BUNDLE_BINARY;
}
}
}
if (t instanceof Tag) {
return TreeNodeType.OTHER_TAG;
}
/*if(t instanceof StringNode){
StringNode sn=(StringNode)t;
String name = sn.getItem().getName();
if(name!=null){
switch(name){
case TagTreeModel.FOLDER_BINARY_DATA:
break;
case TagTreeModel.FOLDER_BUTTONS:
break;
case TagTreeModel.FOLDER_FONTS:
break;
case TagTreeModel.FOLDER_FRAMES:
break;
case TagTreeModel.FOLDER_IMAGES:
break;
case TagTreeModel.FOLDER_MORPHSHAPES:
break;
case TagTreeModel.FOLDER_MOVIES:
break;
case TagTreeModel.FOLDER_OTHERS:
break;
case TagTreeModel.FOLDER_SCRIPTS:
break;
case TagTreeModel.FOLDER_SHAPES:
break;
case TagTreeModel.FOLDER_SOUNDS:
break;
case TagTreeModel.FOLDER_SPRITES:
break;
case TagTreeModel.FOLDER_TEXTS:
break;
}
}
}*/
return TreeNodeType.FOLDER;
}
public List<TreeElementItem> getTagsWithType(List<TreeElementItem> list, TreeNodeType type) {
List<TreeElementItem> ret = new ArrayList<>();
for (TreeElementItem item : list) {
TreeNodeType ttype = getTreeNodeType(item);
if (type == ttype) {
ret.add(item);
}
}
return ret;
}
public TreeItem getCurrentTreeItem() {
TreeNode treeNode = (TreeNode) getLastSelectedPathComponent();
if (treeNode == null) {
return null;
}
return treeNode.getItem();
}
}
/*
* Copyright (C) 2010-2014 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;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.gui.abc.treenodes.TreeElement;
import com.jpexs.decompiler.flash.gui.treenodes.SWFNode;
import com.jpexs.decompiler.flash.gui.treenodes.TagTreeRoot;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.DefineFont3Tag;
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineFontTag;
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag;
import com.jpexs.decompiler.flash.tags.DefineShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineShape3Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineShapeTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.decompiler.flash.treeitems.StringItem;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.treenodes.ContainerNode;
import com.jpexs.decompiler.flash.treenodes.FrameNode;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import com.jpexs.helpers.Helper;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
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;
/**
*
* @author JPEXS
*/
public class TagTree extends JTree implements ActionListener {
private static final String ACTION_RAW_EDIT = "RAWEDIT";
private static final String ACTION_JUMP_TO_CHARACTER = "JUMPTOCHARACTER";
private static final String ACTION_REMOVE_ITEM = "REMOVEITEM";
private static final String ACTION_REMOVE_ITEM_WITH_DEPENDENCIES = "REMOVEITEMWITHDEPENDENCIES";
private static final String ACTION_CLOSE_SWF = "CLOSESWF";
private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE";
private final MainPanel mainPanel;
public class TagTreeCellRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
TreeNode treeNode = (TreeNode) value;
TreeItem val = treeNode.getItem();
TreeNodeType type = getTreeNodeType(val);
if (type != null) {
if (type == TreeNodeType.FOLDER && expanded) {
type = TreeNodeType.FOLDER_OPEN;
}
String itemName = type.toString();
if (type == TreeNodeType.FOLDER || type == TreeNodeType.FOLDER_OPEN) {
if (val instanceof StringItem) {
StringItem si = (StringItem) val;
if (!TagTreeRoot.FOLDER_ROOT.equals(si.getName())) {
itemName = "folder" + si.getName();
}
}
}
String tagTypeStr = itemName.toLowerCase().replace("_", "");
setIcon(View.getIcon(tagTypeStr + "16"));
}
Font font = getFont();
boolean isModified = false;
if (treeNode instanceof TreeNode) {
if (treeNode.getItem() instanceof Tag) {
Tag tag = (Tag) treeNode.getItem();
if (tag.isModified()) {
isModified = true;
}
}
}
if (isModified) {
font = font.deriveFont(Font.BOLD);
} else {
font = font.deriveFont(Font.PLAIN);
}
setFont(font);
setUI(new BasicLabelUI());
setOpaque(false);
//setBackground(Color.green);
setBackgroundNonSelectionColor(Color.white);
//setBackgroundSelectionColor(Color.ORANGE);
return this;
}
}
TagTree(TagTreeModel treeModel, MainPanel mainPanel) {
super(treeModel);
this.mainPanel = mainPanel;
setCellRenderer(new TagTreeCellRenderer());
setRootVisible(false);
setBackground(Color.white);
setUI(new BasicTreeUI() {
@Override
public void paint(Graphics g, JComponent c) {
setHashColor(Color.gray);
super.paint(g, c);
}
});
}
public static TreeNodeType getTreeNodeType(TreeItem t) {
if ((t instanceof DefineFontTag)
|| (t instanceof DefineFont2Tag)
|| (t instanceof DefineFont3Tag)
|| (t instanceof DefineFont4Tag)
|| (t instanceof DefineCompactedFont)) {
return TreeNodeType.FONT;
}
if ((t instanceof DefineTextTag)
|| (t instanceof DefineText2Tag)
|| (t instanceof DefineEditTextTag)) {
return TreeNodeType.TEXT;
}
if ((t instanceof DefineBitsTag)
|| (t instanceof DefineBitsJPEG2Tag)
|| (t instanceof DefineBitsJPEG3Tag)
|| (t instanceof DefineBitsJPEG4Tag)
|| (t instanceof DefineBitsLosslessTag)
|| (t instanceof DefineBitsLossless2Tag)) {
return TreeNodeType.IMAGE;
}
if ((t instanceof DefineShapeTag)
|| (t instanceof DefineShape2Tag)
|| (t instanceof DefineShape3Tag)
|| (t instanceof DefineShape4Tag)) {
return TreeNodeType.SHAPE;
}
if ((t instanceof DefineMorphShapeTag) || (t instanceof DefineMorphShape2Tag)) {
return TreeNodeType.MORPH_SHAPE;
}
if (t instanceof DefineSpriteTag) {
return TreeNodeType.SPRITE;
}
if ((t instanceof DefineButtonTag) || (t instanceof DefineButton2Tag)) {
return TreeNodeType.BUTTON;
}
if (t instanceof ASMSource) {
return TreeNodeType.AS;
}
if (t instanceof ScriptPack) {
return TreeNodeType.AS;
}
if (t instanceof AS2PackageNodeItem) {
return TreeNodeType.PACKAGE;
}
if (t instanceof AS3PackageNodeItem) {
return TreeNodeType.PACKAGE;
}
if (t instanceof FrameNodeItem) {
return TreeNodeType.FRAME;
}
if (t instanceof ShowFrameTag) {
return TreeNodeType.SHOW_FRAME;
}
if (t instanceof DefineVideoStreamTag) {
return TreeNodeType.MOVIE;
}
if ((t instanceof DefineSoundTag) || (t instanceof SoundStreamHeadTag) || (t instanceof SoundStreamHead2Tag)) {
return TreeNodeType.SOUND;
}
if (t instanceof DefineBinaryDataTag) {
return TreeNodeType.BINARY_DATA;
}
if (t instanceof SWF) {
return TreeNodeType.FLASH;
}
if (t instanceof SWFList) {
SWFList slist = (SWFList) t;
if (slist.name != null) {
if (slist.name.toLowerCase().endsWith(".zip")) {
return TreeNodeType.BUNDLE_ZIP;
}
if (slist.name.toLowerCase().endsWith(".swc")) {
return TreeNodeType.BUNDLE_SWC;
} else {
return TreeNodeType.BUNDLE_BINARY;
}
}
}
if (t instanceof Tag) {
return TreeNodeType.OTHER_TAG;
}
return TreeNodeType.FOLDER;
}
public void createContextMenu(final List<SWFList> swfs) {
final JPopupMenu contextPopupMenu = new JPopupMenu();
final JMenuItem expandRecursiveMenuItem = new JMenuItem(mainPanel.translate("contextmenu.expandAll"));
expandRecursiveMenuItem.addActionListener(this);
expandRecursiveMenuItem.setActionCommand(ACTION_EXPAND_RECURSIVE);
contextPopupMenu.add(expandRecursiveMenuItem);
final JMenuItem removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove"));
removeMenuItem.addActionListener(this);
removeMenuItem.setActionCommand(ACTION_REMOVE_ITEM);
contextPopupMenu.add(removeMenuItem);
final JMenuItem removeWithDependenciesMenuItem = new JMenuItem(mainPanel.translate("contextmenu.removeWithDependencies"));
removeWithDependenciesMenuItem.addActionListener(this);
removeWithDependenciesMenuItem.setActionCommand(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
contextPopupMenu.add(removeWithDependenciesMenuItem);
final JMenuItem exportSelectionMenuItem = new JMenuItem(mainPanel.translate("menu.file.export.selection"));
exportSelectionMenuItem.setActionCommand(MainFrameRibbonMenu.ACTION_EXPORT_SEL);
exportSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(exportSelectionMenuItem);
final JMenuItem replaceSelectionMenuItem = new JMenuItem(mainPanel.translate("button.replace"));
replaceSelectionMenuItem.setActionCommand(MainPanel.ACTION_REPLACE);
replaceSelectionMenuItem.addActionListener(mainPanel);
contextPopupMenu.add(replaceSelectionMenuItem);
final JMenuItem rawEditMenuItem = new JMenuItem(mainPanel.translate("contextmenu.rawEdit"));
rawEditMenuItem.setActionCommand(ACTION_RAW_EDIT);
rawEditMenuItem.addActionListener(this);
rawEditMenuItem.setVisible(false);
contextPopupMenu.add(rawEditMenuItem);
final JMenuItem jumpToCharacterMenuItem = new JMenuItem(mainPanel.translate("contextmenu.jumpToCharacter"));
jumpToCharacterMenuItem.setActionCommand(ACTION_JUMP_TO_CHARACTER);
jumpToCharacterMenuItem.addActionListener(this);
jumpToCharacterMenuItem.setVisible(false);
contextPopupMenu.add(jumpToCharacterMenuItem);
final JMenuItem closeSelectionMenuItem = new JMenuItem(mainPanel.translate("contextmenu.closeSwf"));
closeSelectionMenuItem.setActionCommand(ACTION_CLOSE_SWF);
closeSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(closeSelectionMenuItem);
final JMenu moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag"));
contextPopupMenu.add(moveTagMenu);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int row = getClosestRowForLocation(e.getX(), e.getY());
int[] selectionRows = getSelectionRows();
if (!Helper.contains(selectionRows, row)) {
setSelectionRow(row);
}
TreePath[] paths = getSelectionPaths();
if (paths == null || paths.length == 0) {
return;
}
boolean allSelectedIsTagOrFrame = true;
for (TreePath treePath : paths) {
TreeNode treeNode = (TreeNode) treePath.getLastPathComponent();
TreeItem tag = treeNode.getItem();
if (!(tag instanceof Tag) && !(tag instanceof FrameNodeItem)) {
allSelectedIsTagOrFrame = false;
break;
}
}
replaceSelectionMenuItem.setVisible(false);
closeSelectionMenuItem.setVisible(false);
moveTagMenu.setVisible(false);
expandRecursiveMenuItem.setVisible(false);
if (paths.length == 1) {
TreeNode treeNode = (TreeNode) paths[0].getLastPathComponent();
TreeItem item = ((TreeNode) treeNode).getItem();
if (item instanceof ImageTag && ((ImageTag) item).importSupported()) {
replaceSelectionMenuItem.setVisible(true);
}
if (item instanceof DefineBinaryDataTag) {
replaceSelectionMenuItem.setVisible(true);
}
if (item instanceof DefineSoundTag) {
replaceSelectionMenuItem.setVisible(true);
}
if (treeNode instanceof SWFNode) {
closeSelectionMenuItem.setVisible(true);
}
if (item instanceof Tag && swfs.size() > 1) {
final Tag tag = (Tag) item;
moveTagMenu.removeAll();
for (SWFList targetSwfList : swfs) {
for (final SWF targetSwf : targetSwfList) {
if (targetSwf != tag.getSwf()) {
JMenuItem swfItem = new JMenuItem(targetSwf.getShortFileName());
swfItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
tag.getSwf().tags.remove(tag);
tag.setSwf(targetSwf);
targetSwf.tags.add(tag);
mainPanel.refreshTree();
}
});
moveTagMenu.add(swfItem);
}
}
}
moveTagMenu.setVisible(true);
}
TreeModel model = getModel();
expandRecursiveMenuItem.setVisible(model.getChildCount(treeNode) > 0);
jumpToCharacterMenuItem.setVisible(item instanceof CharacterIdTag && !(item instanceof CharacterTag));
rawEditMenuItem.setVisible(item instanceof Tag);
}
removeMenuItem.setVisible(allSelectedIsTagOrFrame);
exportSelectionMenuItem.setEnabled(hasExportableNodes());
contextPopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_RAW_EDIT: {
TreeItem item = getCurrentTreeItem();
if (item == null) {
return;
}
mainPanel.showGenericTag((Tag) item);
}
break;
case ACTION_JUMP_TO_CHARACTER: {
TreeItem item = getCurrentTreeItem();
if (item == null || !(item instanceof CharacterIdTag)) {
return;
}
CharacterIdTag characterIdTag = (CharacterIdTag) item;
mainPanel.setTreeItem(item.getSwf().characters.get(characterIdTag.getCharacterId()));
}
break;
case ACTION_EXPAND_RECURSIVE: {
TreePath path = getSelectionPath();
if (path == null) {
return;
}
View.expandTreeNodesRecursive(this, path, true);
}
break;
case ACTION_REMOVE_ITEM:
case ACTION_REMOVE_ITEM_WITH_DEPENDENCIES:
List<TreeNode> sel = getSelected(this);
List<Tag> tagsToRemove = new ArrayList<>();
for (TreeNode o : sel) {
TreeItem tag = o.getItem();
if (tag instanceof Tag) {
tagsToRemove.add((Tag) tag);
} else if (tag instanceof FrameNodeItem) {
FrameNodeItem frameNode = (FrameNodeItem) tag;
Frame frame = frameNode.getParent().getTimeline().frames.get(frameNode.getFrame() - 1);
if (frame.showFrameTag != null) {
tagsToRemove.add(frame.showFrameTag);
} else {
// this should be the last frame, so remove the inner tags
tagsToRemove.addAll(frame.innerTags);
}
}
}
boolean removeDependencies = e.getActionCommand().equals(ACTION_REMOVE_ITEM_WITH_DEPENDENCIES);
if (tagsToRemove.size() == 1) {
Tag tag = tagsToRemove.get(0);
if (View.showConfirmDialog(this, mainPanel.translate("message.confirm.remove").replace("%item%", tag.toString()), mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
tag.getSwf().removeTag(tag, removeDependencies);
mainPanel.refreshTree();
}
} else if (tagsToRemove.size() > 1) {
if (View.showConfirmDialog(this, mainPanel.translate("message.confirm.removemultiple").replace("%count%", Integer.toString(tagsToRemove.size())), mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
for (Tag tag : tagsToRemove) {
tag.getSwf().removeTag(tag, removeDependencies);
}
mainPanel.refreshTree();
}
}
break;
case ACTION_CLOSE_SWF: {
Main.closeFile(mainPanel.getCurrentSwfList());
}
}
}
public boolean hasExportableNodes() {
return !getSelection(mainPanel.getCurrentSwf()).isEmpty();
}
public List<TreeNode> getAllSubs(JTree tree, TreeNode o) {
TagTreeModel tm = (TagTreeModel) tree.getModel();
List<TreeNode> ret = new ArrayList<>();
for (int i = 0; i < tm.getChildCount(o); i++) {
TreeNode c = tm.getChild(o, i);
ret.add(c);
ret.addAll(getAllSubs(tree, c));
}
return ret;
}
public List<TreeNode> getAllSelected(TagTree tree) {
TreeSelectionModel tsm = tree.getSelectionModel();
TreePath[] tps = tsm.getSelectionPaths();
List<TreeNode> ret = new ArrayList<>();
if (tps == null) {
return ret;
}
for (TreePath tp : tps) {
TreeNode treeNode = (TreeNode) tp.getLastPathComponent();
ret.add(treeNode);
ret.addAll(getAllSubs(tree, treeNode));
}
return ret;
}
public List<TreeNode> getSelected(JTree tree) {
TreeSelectionModel tsm = tree.getSelectionModel();
TreePath[] tps = tsm.getSelectionPaths();
List<TreeNode> ret = new ArrayList<>();
if (tps == null) {
return ret;
}
for (TreePath tp : tps) {
TreeNode treeNode = (TreeNode) tp.getLastPathComponent();
ret.add(treeNode);
}
return ret;
}
public List<Object> getSelection(SWF swf) {
List<Object> ret = new ArrayList<>();
List<TreeNode> sel = getAllSelected(this);
for (TreeNode d : sel) {
if (d.getItem().getSwf() != swf) {
continue;
}
if (d instanceof ContainerNode) {
ContainerNode n = (ContainerNode) d;
TreeNodeType nodeType = TagTree.getTreeNodeType(n.getItem());
if (nodeType == TreeNodeType.IMAGE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.SHAPE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.MORPH_SHAPE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.AS) {
ret.add(n);
}
if (nodeType == TreeNodeType.MOVIE) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.SOUND) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.BINARY_DATA) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.TEXT) {
ret.add((Tag) n.getItem());
}
if (nodeType == TreeNodeType.FONT) {
ret.add((Tag) n.getItem());
}
}
if (d instanceof FrameNode) {
FrameNode fn = (FrameNode) d;
if (!fn.scriptsNode) {
ret.add(d.getItem());
}
}
if (d instanceof TreeElement) {
if (((TreeElement) d).isLeaf()) {
TreeElement treeElement = (TreeElement) d;
ret.add((ScriptPack) treeElement.getItem());
}
}
}
return ret;
}
public List<TreeElementItem> getTagsWithType(List<TreeElementItem> list, TreeNodeType type) {
List<TreeElementItem> ret = new ArrayList<>();
for (TreeElementItem item : list) {
TreeNodeType ttype = getTreeNodeType(item);
if (type == ttype) {
ret.add(item);
}
}
return ret;
}
public TreeItem getCurrentTreeItem() {
TreeNode treeNode = (TreeNode) getLastSelectedPathComponent();
if (treeNode == null) {
return null;
}
return treeNode.getItem();
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2010-2014 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;
/**
*
* @author JPEXS
*/
public enum TreePanelMode {
TAG_TREE, DUMP_TREE
}
@@ -733,7 +733,7 @@ public class ActionPanel extends JPanel implements ActionListener, SearchListene
if (text.trim().startsWith("#hexdata")) {
src.setActionBytes(Helper.getBytesFromHexaText(text));
} else {
src.setActions(ASMParser.parse(0, src.getPos(), true, text, src.getSwf().version, false));
src.setActions(ASMParser.parse(0, true, text, src.getSwf().version, false));
}
src.setModified();
setSource(this.src, false);
@@ -0,0 +1,171 @@
/*
* Copyright (C) 2010-2014 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.dumpview;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.MainPanel;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.helpers.Helper;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
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;
/**
*
* @author JPEXS
*/
public class DumpTree extends JTree implements ActionListener {
private static final String ACTION_CLOSE_SWF = "CLOSESWF";
private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE";
private final MainPanel mainPanel;
public class DumpTreeCellRenderer extends DefaultTreeCellRenderer {
@Override
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
//DumpInfo dumpInfo = (DumpInfo) value;
setUI(new BasicLabelUI());
setOpaque(false);
setBackgroundNonSelectionColor(Color.white);
return this;
}
}
public DumpTree(DumpTreeModel treeModel, MainPanel mainPanel) {
super(treeModel);
this.mainPanel = mainPanel;
setCellRenderer(new DumpTreeCellRenderer());
setRootVisible(false);
setBackground(Color.white);
setUI(new BasicTreeUI() {
@Override
public void paint(Graphics g, JComponent c) {
setHashColor(Color.gray);
super.paint(g, c);
}
});
}
public void createContextMenu() {
final JPopupMenu contextPopupMenu = new JPopupMenu();
final JMenuItem expandRecursiveMenuItem = new JMenuItem(mainPanel.translate("contextmenu.expandAll"));
expandRecursiveMenuItem.addActionListener(this);
expandRecursiveMenuItem.setActionCommand(ACTION_EXPAND_RECURSIVE);
contextPopupMenu.add(expandRecursiveMenuItem);
final JMenuItem closeSelectionMenuItem = new JMenuItem(mainPanel.translate("contextmenu.closeSwf"));
closeSelectionMenuItem.setActionCommand(ACTION_CLOSE_SWF);
closeSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(closeSelectionMenuItem);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int row = getClosestRowForLocation(e.getX(), e.getY());
int[] selectionRows = getSelectionRows();
if (!Helper.contains(selectionRows, row)) {
setSelectionRow(row);
}
TreePath[] paths = getSelectionPaths();
if (paths == null || paths.length == 0) {
return;
}
closeSelectionMenuItem.setVisible(false);
expandRecursiveMenuItem.setVisible(false);
if (paths.length == 1) {
DumpInfo treeNode = (DumpInfo) paths[0].getLastPathComponent();
if (treeNode instanceof DumpInfoSwfNode) {
closeSelectionMenuItem.setVisible(true);
}
TreeModel model = getModel();
expandRecursiveMenuItem.setVisible(model.getChildCount(treeNode) > 0);
}
contextPopupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case ACTION_EXPAND_RECURSIVE: {
TreePath path = getSelectionPath();
if (path == null) {
return;
}
View.expandTreeNodesRecursive(this, path, true);
}
break;
case ACTION_CLOSE_SWF: {
Main.closeFile(mainPanel.getCurrentSwfList());
}
}
}
@Override
public void setModel(TreeModel tm) {
super.setModel(tm);
if (tm != null) {
int rowCount = tm.getChildCount(tm.getRoot());
for (int i = rowCount - 1; i >= 0; i--) {
expandRow(i);
}
}
}
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2010-2014 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.dumpview;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import java.util.List;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
*
* @author JPEXS
*/
public class DumpTreeModel implements TreeModel {
private final DumpInfo root;
public DumpTreeModel(List<SWFList> swfs) {
DumpInfo root = new DumpInfo("root", "", null, 0, 0);
for (SWFList swfList : swfs) {
for (SWF swf : swfList) {
swf.dumpInfo.name = swf.getFileTitle();
root.childInfos.add(swf.dumpInfo);
}
}
this.root = root;
}
@Override
public Object getRoot() {
return root;
}
@Override
public Object getChild(Object o, int i) {
return ((DumpInfo) o).childInfos.get(i);
}
@Override
public int getChildCount(Object o) {
return ((DumpInfo) o).childInfos.size();
}
@Override
public boolean isLeaf(Object o) {
return ((DumpInfo) o).childInfos.isEmpty();
}
@Override
public void valueForPathChanged(TreePath tp, Object o) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public int getIndexOfChild(Object o, Object o1) {
return ((DumpInfo) o).childInfos.indexOf(o1);
}
@Override
public void addTreeModelListener(TreeModelListener tl) {
}
@Override
public void removeTreeModelListener(TreeModelListener tl) {
}
}
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2010-2014 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.dumpview;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.gui.HexView;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author JPEXS
*/
public class DumpViewPanel extends JPanel {
private final JLabel dumpViewLabel;
private final HexView dumpViewHexTable;
public DumpViewPanel() {
super(new BorderLayout());
dumpViewLabel = new JLabel();
dumpViewLabel.setMinimumSize(new Dimension(100, 20));
add(dumpViewLabel, BorderLayout.SOUTH);
dumpViewHexTable = new HexView();
add(new JScrollPane(dumpViewHexTable), BorderLayout.CENTER);
}
private int getEndIndex(DumpInfo dumpInfo) {
int end = (int) dumpInfo.startByte;
if (dumpInfo.lengthBytes != 0) {
end += dumpInfo.lengthBytes;
} else {
int bits = dumpInfo.startBit + dumpInfo.lengthBits;
end += bits / 8;
if (bits % 8 != 0) {
end++;
}
}
return end - 1;
}
public void setData(byte[] data, DumpInfo dumpInfo) {
List<DumpInfo> dumpInfos = new ArrayList<>();
DumpInfo di = dumpInfo;
while (di.parent != null) {
dumpInfos.add(di);
di = di.parent;
}
long[] highlightStarts = new long[dumpInfos.size()];
long[] highlightEnds = new long[dumpInfos.size()];
for (int i = 0; i < dumpInfos.size(); i++) {
DumpInfo di2 = dumpInfos.get(highlightStarts.length - i - 1);
highlightStarts[i] = di2.startByte;
highlightEnds[i] = getEndIndex(di2);
}
dumpViewHexTable.setData(data, highlightStarts, highlightEnds);
if (dumpInfo.lengthBytes != 0 || dumpInfo.lengthBits != 0) {
int selectionStart = (int) dumpInfo.startByte;
int selectionEnd = getEndIndex(dumpInfo);
dumpViewHexTable.scrollToByte(highlightStarts, highlightEnds);
setLabelText("startByte: " + dumpInfo.startByte
+ " startBit: " + dumpInfo.startBit
+ " lengthBytes: " + dumpInfo.lengthBytes
+ " lengthBits: " + dumpInfo.lengthBits
+ " selectionStart: " + selectionStart
+ " selectionEnd: " + selectionEnd);
}
repaint();
}
public void setLabelText(String text) {
dumpViewLabel.setText(text);
}
}