diff --git a/src/com/jpexs/decompiler/flash/gui/ExportDialog.java b/src/com/jpexs/decompiler/flash/gui/ExportDialog.java index d611a8ace..6c74b0a66 100644 --- a/src/com/jpexs/decompiler/flash/gui/ExportDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/ExportDialog.java @@ -71,7 +71,7 @@ public class ExportDialog extends AppDialog { TagTreeModel.FOLDER_IMAGES, TagTreeModel.FOLDER_MOVIES, TagTreeModel.FOLDER_SOUNDS, - TagTreeModel.FOLDER_SPRITES, + TagTreeModel.FOLDER_SCRIPTS, TagTreeModel.FOLDER_BINARY_DATA, TagTreeModel.FOLDER_FRAMES, TagTreeModel.FOLDER_FONTS, diff --git a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java new file mode 100644 index 000000000..409045811 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2014 Jindra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.timeline.Frame; +import com.jpexs.decompiler.flash.treeitems.TreeItem; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.helpers.Cache; +import com.jpexs.helpers.SerializableImage; +import com.sun.javafx.scene.control.skin.VirtualFlow; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + * + * @author JPEXS + */ +public class FolderPreviewPanel extends JPanel { + + private static final ExecutorService executor; + private List items; + private int selectedIndex = -1; + + public Map selectedItems = new HashMap<>(); + + private Cache cachedPreviews; + private static final int PREVIEW_SIZE = 150; + private static final int BORDER_SIZE = 5; + private static final int LABEL_HEIGHT=20; + private static final int CELL_HEIGHT = 2*BORDER_SIZE + PREVIEW_SIZE + LABEL_HEIGHT; + private static final int CELL_WIDTH = 2*BORDER_SIZE + PREVIEW_SIZE; + private static final SerializableImage noImage = new SerializableImage(PREVIEW_SIZE,PREVIEW_SIZE,BufferedImage.TYPE_INT_ARGB); + static{ + noImage.fillTransparent(); + executor = Executors.newFixedThreadPool(Configuration.parallelSpeedUp.get() ? Configuration.parallelThreadCount.get() : 1); + } + + + public FolderPreviewPanel(final MainPanel mainPanel, List items) { + this.items = items; + cachedPreviews = Cache.getInstance(false); + + addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() >1){ + if(selectedIndex>-1){ + mainPanel.setTagTreeSelectedNode(FolderPreviewPanel.this.items.get(selectedIndex)); + } + } + } + + + + @Override + public void mousePressed(MouseEvent e) { + int width = getWidth(); + + int cols = width / CELL_WIDTH; + int rows = (int)Math.ceil(FolderPreviewPanel.this.items.size() / (float)cols); + int x = e.getX() / CELL_WIDTH; + int y = e.getY() / CELL_HEIGHT; + int index=y*cols+x; + if(index>=FolderPreviewPanel.this.items.size()){ + return; + } + + + if(e.getButton() == MouseEvent.BUTTON1 || selectedItems.isEmpty()){ + if(!e.isControlDown()){ + selectedItems.clear(); + } + int oldSelectedIndex = selectedIndex; + selectedIndex = index; + + if(e.isShiftDown() && oldSelectedIndex>-1){ + int minindex=Math.min(selectedIndex, oldSelectedIndex); + int maxindex=Math.max(selectedIndex, oldSelectedIndex); + for(int i=minindex;i<=maxindex;i++){ + selectedItems.put(i, FolderPreviewPanel.this.items.get(i)); + } + selectedIndex = oldSelectedIndex; + }else{ + TreeItem ti=FolderPreviewPanel.this.items.get(index); + if(!selectedItems.containsKey(selectedIndex)){ + selectedItems.put(selectedIndex,ti); + }else{ + selectedItems.remove(selectedIndex); + selectedIndex = -1; + } + } + } + + if(e.getButton() == MouseEvent.BUTTON3){ + mainPanel.tagTree.updateContextMenu(mainPanel.tagTree.swfs, new ArrayList<>(selectedItems.values())); + mainPanel.tagTree.contextPopupMenu.show(FolderPreviewPanel.this, e.getX(),e.getY()); + } + repaint(); + } + +}); + } + + public synchronized void setItems(List items) { + this.items = items; + cachedPreviews.clear(); + revalidate(); + repaint(); + selectedItems.clear(); + selectedIndex = -1; + } + + + @Override + public Dimension getPreferredSize() { + int width = getParent().getSize().width-20; + int cols = width / CELL_WIDTH; + int rows = (int)Math.ceil(items.size() / (float)cols); + int height = rows*CELL_HEIGHT; + return (new Dimension(width,height)); + } + + + + @Override + public void paint(Graphics g) { + super.paint(g); + Rectangle r = getVisibleRect(); + int width = getWidth(); + + int cols = width / CELL_WIDTH; + int rows = (int)Math.ceil(items.size() / (float)cols); + int height = rows*CELL_HEIGHT; + + int start_y = r.y / CELL_HEIGHT; + JLabel l = new JLabel(); + Font f = l.getFont().deriveFont(AffineTransform.getScaleInstance(0.8, 0.8)); + int finish_y = (int)Math.ceil((r.y + r.height) / (float)CELL_HEIGHT); + g.setColor(Color.black); + for(int y=start_y;y<=finish_y;y++){ + for(int x=0;x() { + + @Override + public Void call() throws Exception { + cachedPreviews.put(index, renderImage(treeItem.getSwf(), treeItem)); + View.execInEventDispatch(new Runnable() { + + @Override + public void run() { + revalidate(); + repaint(); + } + }); + return null; + } + + }); + + } + + private SerializableImage renderImage(SWF swf, TreeItem treeItem) { + + int width = 0; + int height = 0; + SerializableImage imgSrc = null; + Matrix m = new Matrix(); + if (treeItem instanceof Frame) { + Frame fn = (Frame) treeItem; + RECT rect = swf.displayRect; + imgSrc = SWF.frameToImageGet(swf.getTimeline(), fn.frame, 0, null, 0, rect, new Matrix(), new ColorTransform(), null, true, 1.0); + width = (imgSrc.getWidth()); + height = (imgSrc.getHeight()); + } else if (treeItem instanceof ImageTag) { + imgSrc = ((ImageTag) treeItem).getImage(); + width = (imgSrc.getWidth()); + height = (imgSrc.getHeight()); + } else if (treeItem instanceof BoundedTag) { + BoundedTag boundedTag = (BoundedTag) treeItem; + RECT rect = boundedTag.getRect(new HashSet()); + width = (int) (rect.getWidth() / SWF.unitDivisor) + 1; + height = (int) (rect.getHeight() / SWF.unitDivisor) + 1; + m.translate(-rect.Xmin, -rect.Ymin); + } + + int w1 = width; + int h1 = height; + int w2 = PREVIEW_SIZE; + int h2 = PREVIEW_SIZE; + + int w; + int h = h1 * w2 / w1; + if (h > h2) { + w = w1 * h2 / h1; + h = h2; + } else { + w = w2; + } + + double scale = (double) w / (double) w1; + if (w1 <= w2 && h1 <= h2) { + scale = 1; + } + + m = m.preConcatenate(Matrix.getScaleInstance(scale)); + width = (int) (scale * width); + height = (int) (scale * height); + if (width == 0 || height == 0) { + return null; + } + + SerializableImage image = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB); + image.fillTransparent(); + if (imgSrc == null) { + DrawableTag drawable = (DrawableTag) treeItem; + drawable.toImage(0, 0, 0, null, 0, image, m, new ColorTransform()); + } else { + Graphics2D g = (Graphics2D) image.getGraphics(); + g.setTransform(m.toTransform()); + g.drawImage(imgSrc.getBufferedImage(), 0, 0, null); + } + return image; + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 87228fcb5..41d0bbe33 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -127,6 +127,7 @@ import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.sound.SoundFormat; import com.jpexs.decompiler.flash.xfl.FLAVersion; +import com.jpexs.helpers.Cache; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; import com.jpexs.helpers.Path; @@ -139,6 +140,7 @@ import java.awt.Component; import java.awt.Desktop; import java.awt.FlowLayout; import java.awt.Font; +import java.awt.Image; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; @@ -227,7 +229,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private final FlashPlayerPanel flashPanel; private final JPanel contentPanel; private final JPanel displayPanel; - private JPanel folderPreviewPanel; + public FolderPreviewPanel folderPreviewPanel; private boolean isWelcomeScreen = true; private static final String CARDPREVIEWPANEL = "Preview card"; private static final String CARDFOLDERPREVIEWPANEL = "Folder preview card"; @@ -350,7 +352,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private JPanel createFolderPreviewCard() { JPanel folderPreviewCard = new JPanel(new BorderLayout()); - folderPreviewPanel = new JPanel(new WrapLayout(FlowLayout.LEFT)); + folderPreviewPanel = new FolderPreviewPanel(this,new ArrayList()); folderPreviewCard.add(new JScrollPane(folderPreviewPanel), BorderLayout.CENTER); return folderPreviewCard; @@ -987,7 +989,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec public List exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException { List ret = new ArrayList<>(); - List sel = tagTree.getAllSelected(tagTree); + List sel = folderPreviewPanel.selectedItems.isEmpty()?tagTree.getAllSelected(tagTree):new ArrayList<>(folderPreviewPanel.selectedItems.values()); List allSwfs = new ArrayList<>(); for (SWFList swfList : swfs) { @@ -2274,6 +2276,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec if (flashPanel != null) { //flashPanel.specialPlayback = false; } + folderPreviewPanel.setItems(new ArrayList()); previewPanel.clear(); if (soundThread != null) { soundThread.pause(); @@ -2457,94 +2460,70 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec previewPanel.showTextPanel(textTag); } + + private void showFolderPreview(TreeItem treeNode) { - folderPreviewPanel.removeAll(); + List folderPreviewItems = new ArrayList<>(); FolderItem item = (FolderItem) treeNode; String folderName = item.getName(); SWF swf = item.swf; - JPanel panel = folderPreviewPanel; switch (folderName) { case TagTreeModel.FOLDER_SHAPES: for (Tag tag : swf.tags) { if (tag instanceof ShapeTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; case TagTreeModel.FOLDER_MORPHSHAPES: for (Tag tag : swf.tags) { if (tag instanceof MorphShapeTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; case TagTreeModel.FOLDER_SPRITES: for (Tag tag : swf.tags) { if (tag instanceof DefineSpriteTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; case TagTreeModel.FOLDER_BUTTONS: for (Tag tag : swf.tags) { if (tag instanceof ButtonTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; case TagTreeModel.FOLDER_FONTS: for (Tag tag : swf.tags) { if (tag instanceof FontTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; case TagTreeModel.FOLDER_FRAMES: for (Frame frame : swf.getTimeline().getFrames()) { - Component c = PreviewImage.createFolderPreviewImage(this, frame); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(frame); } break; case TagTreeModel.FOLDER_IMAGES: for (Tag tag : swf.tags) { if (tag instanceof ImageTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; case TagTreeModel.FOLDER_TEXTS: for (Tag tag : swf.tags) { if (tag instanceof TextTag) { - Component c = PreviewImage.createFolderPreviewImage(this, tag); - if (c != null) { - panel.add(c); - } + folderPreviewItems.add(tag); } } break; } - panel.revalidate(); - panel.repaint(); + folderPreviewPanel.setItems(folderPreviewItems); } public void expandSwfNodes() { diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewImage.java b/src/com/jpexs/decompiler/flash/gui/PreviewImage.java deleted file mode 100644 index 5f34f9017..000000000 --- a/src/com/jpexs/decompiler/flash/gui/PreviewImage.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * 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 . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.tags.base.DrawableTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.timeline.Frame; -import com.jpexs.decompiler.flash.treeitems.TreeItem; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.helpers.SerializableImage; -import java.awt.AlphaComposite; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.geom.AffineTransform; -import java.util.HashSet; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; - -/** - * - * @author JPEXS - */ -public class PreviewImage extends JPanel { - - private static final ExecutorService executor; - private static final int PREVIEW_SIZE = 150; - private static final int BORDER_SIZE = 5; - private Image image; - private boolean rendering; - private final MainPanel mainPanel; - private final TreeItem treeItem; - - static { - executor = Executors.newFixedThreadPool(Configuration.parallelSpeedUp.get() ? Configuration.parallelThreadCount.get() : 1); - } - - /** - * - * @param mainPanel - * @param treeItem - */ - public PreviewImage(final MainPanel mainPanel, final TreeItem treeItem) { - this.mainPanel = mainPanel; - this.treeItem = treeItem; - Dimension dim = new Dimension(PREVIEW_SIZE + 2 * BORDER_SIZE, PREVIEW_SIZE + 2 * BORDER_SIZE); - setMinimumSize(dim); - setMaximumSize(dim); - setPreferredSize(dim); - setSize(dim); - setLayout(null); - setBorder(BorderFactory.createLineBorder(Color.black)); - - if (treeItem instanceof Tag) { - JPopupMenu contextMenu = new JPopupMenu(); - final JMenuItem removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove")); - removeMenuItem.addActionListener(new AbstractAction() { - - @Override - public void actionPerformed(ActionEvent e) { - Tag tag = (Tag) treeItem; - tag.getSwf().removeTag(tag, false); - mainPanel.refreshTree(); - } - }); - contextMenu.add(removeMenuItem); - final JMenuItem removeWithDependenciesMenuItem = new JMenuItem(mainPanel.translate("contextmenu.removeWithDependencies")); - removeWithDependenciesMenuItem.addActionListener(new AbstractAction() { - - @Override - public void actionPerformed(ActionEvent e) { - Tag tag = (Tag) treeItem; - tag.getSwf().removeTag(tag, true); - mainPanel.refreshTree(); - } - }); - contextMenu.add(removeWithDependenciesMenuItem); - this.setComponentPopupMenu(contextMenu); - } - - this.addMouseListener(new MouseListener() { - - @Override - public void mouseClicked(MouseEvent e) { - - if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() >= 2) { - mainPanel.setTagTreeSelectedNode(treeItem); - } - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - }); - } - - private synchronized void renderImageTask(final TreeItem treeItem) { - if (rendering) { - return; - } - rendering = true; - executor.submit(new Callable() { - - @Override - public Void call() throws Exception { - image = renderImage(treeItem.getSwf(), treeItem); - View.execInEventDispatch(new Runnable() { - - @Override - public void run() { - revalidate(); - repaint(); - } - }); - return null; - } - - }); - - } - - private Image renderImage(SWF swf, TreeItem treeItem) { - - int width = 0; - int height = 0; - SerializableImage imgSrc = null; - Matrix m = new Matrix(); - if (treeItem instanceof Frame) { - Frame fn = (Frame) treeItem; - RECT rect = swf.displayRect; - imgSrc = SWF.frameToImageGet(swf.getTimeline(), fn.frame, 0, null, 0, rect, new Matrix(), new ColorTransform(), null, true, 1.0); - width = (imgSrc.getWidth()); - height = (imgSrc.getHeight()); - } else if (treeItem instanceof ImageTag) { - imgSrc = ((ImageTag) treeItem).getImage(); - width = (imgSrc.getWidth()); - height = (imgSrc.getHeight()); - } else if (treeItem instanceof BoundedTag) { - BoundedTag boundedTag = (BoundedTag) treeItem; - RECT rect = boundedTag.getRect(new HashSet()); - width = (int) (rect.getWidth() / SWF.unitDivisor) + 1; - height = (int) (rect.getHeight() / SWF.unitDivisor) + 1; - m.translate(-rect.Xmin, -rect.Ymin); - } - - int w1 = width; - int h1 = height; - int w2 = PREVIEW_SIZE; - int h2 = PREVIEW_SIZE; - - int w; - int h = h1 * w2 / w1; - if (h > h2) { - w = w1 * h2 / h1; - h = h2; - } else { - w = w2; - } - - double scale = (double) w / (double) w1; - if (w1 <= w2 && h1 <= h2) { - scale = 1; - } - - m = m.preConcatenate(Matrix.getScaleInstance(scale)); - width = (int) (scale * width); - height = (int) (scale * height); - if (width == 0 || height == 0) { - return null; - } - - SerializableImage image = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB); - image.fillTransparent(); - if (imgSrc == null) { - DrawableTag drawable = (DrawableTag) treeItem; - drawable.toImage(0, 0, 0, null, 0, image, m, new ColorTransform()); - } else { - Graphics2D g = (Graphics2D) image.getGraphics(); - g.setTransform(m.toTransform()); - g.drawImage(imgSrc.getBufferedImage(), 0, 0, null); - } - return image.getBufferedImage(); - } - - public static Component createFolderPreviewImage(MainPanel mainPanel, TreeItem treeItem) { - JPanel pan = new JPanel(new BorderLayout()); - PreviewImage imagePanel = new PreviewImage(mainPanel, treeItem); - pan.add(imagePanel, BorderLayout.CENTER); - String s; - if (treeItem instanceof Tag) { - s = ((Tag) treeItem).getTagName(); - if (treeItem instanceof CharacterTag) { - s = s + " (" + ((CharacterTag) treeItem).getCharacterId() + ")"; - } - } else { - s = treeItem.toString(); - } - JLabel lab = new JLabel(s); - lab.setFont(lab.getFont().deriveFont(AffineTransform.getScaleInstance(0.8, 0.8))); - pan.add(lab, BorderLayout.SOUTH); - return pan; - } - - @Override - protected void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - g2d.setPaint(View.transparentPaint); - g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); - g2d.setComposite(AlphaComposite.SrcOver); - g2d.setPaint(View.swfBackgroundColor); - g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); - if (image != null) { - int x = (getWidth() / 2) - (image.getWidth(this) / 2); - int y = (getHeight() / 2) - (image.getHeight(this) / 2); - g.drawImage(image, x, y, null); - } else { - renderImageTask(treeItem); - } - } -} diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java index 2f701bced..0f7e1512a 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java @@ -355,58 +355,72 @@ public class TagTree extends JTree implements ActionListener { return ret; } - public void createContextMenu(final List swfs) { - final JPopupMenu contextPopupMenu = new JPopupMenu(); + JMenuItem expandRecursiveMenuItem; + JMenuItem removeMenuItem; + JMenuItem removeWithDependenciesMenuItem; + JMenuItem exportSelectionMenuItem; + JMenuItem replaceSelectionMenuItem; + JMenuItem rawEditMenuItem; + JMenuItem jumpToCharacterMenuItem; + JMenuItem closeSelectionMenuItem; + JMenu addTagMenu; + JMenu moveTagMenu; + JMenuItem openSWFInsideTagMenuItem; + public JPopupMenu contextPopupMenu; + public List swfs; - final JMenuItem expandRecursiveMenuItem = new JMenuItem(mainPanel.translate("contextmenu.expandAll")); + public void createContextMenu(final List swfs) { + this.swfs = swfs; + contextPopupMenu = new JPopupMenu(); + 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 = 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 = 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 = new JMenuItem(mainPanel.translate("menu.file.export.selection")); exportSelectionMenuItem.setActionCommand(MainFrameRibbonMenu.ACTION_EXPORT_SEL); exportSelectionMenuItem.addActionListener(mainPanel); contextPopupMenu.add(exportSelectionMenuItem); - final JMenuItem replaceSelectionMenuItem = new JMenuItem(mainPanel.translate("button.replace")); + 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 = 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 = 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 = new JMenuItem(mainPanel.translate("contextmenu.closeSwf")); closeSelectionMenuItem.setActionCommand(ACTION_CLOSE_SWF); closeSelectionMenuItem.addActionListener(this); contextPopupMenu.add(closeSelectionMenuItem); - final JMenu addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag")); + addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag")); contextPopupMenu.add(addTagMenu); - final JMenu moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag")); + moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag")); contextPopupMenu.add(moveTagMenu); - final JMenuItem openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside")); + openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside")); contextPopupMenu.add(openSWFInsideTagMenuItem); openSWFInsideTagMenuItem.setActionCommand(ACTION_OPEN_SWFINSIDE); openSWFInsideTagMenuItem.addActionListener(this); @@ -444,96 +458,9 @@ public class TagTree extends JTree implements ActionListener { if (paths.length == 1) { TreeItem item = (TreeItem) paths[0].getLastPathComponent(); - - if (item instanceof ImageTag && ((ImageTag) item).importSupported()) { - replaceSelectionMenuItem.setVisible(true); - } - - if (item instanceof DefineBinaryDataTag) { - replaceSelectionMenuItem.setVisible(true); - DefineBinaryDataTag bin = (DefineBinaryDataTag) item; - if (bin.binaryData.length > 8) { - String signature = new String(bin.binaryData, 0, 3, Utf8Helper.charset); - if (Arrays.asList( - "FWS", //Uncompressed Flash - "CWS", //ZLib compressed Flash - "ZWS", //LZMA compressed Flash - "GFX", //Uncompressed ScaleForm GFx - "CFX" //Compressed ScaleForm GFx - ).contains(signature)) { - openSWFInsideTagMenuItem.setVisible(true); - } - } - } - - if (item instanceof DefineSoundTag) { - replaceSelectionMenuItem.setVisible(true); - } - - if (item instanceof SWF) { - closeSelectionMenuItem.setVisible(true); - } - - if (item instanceof FolderItem) { - final FolderItem folderItem = (FolderItem) item; - List allowedTagTypes = getTreeItemClasses(folderItem.getName(), item.getSwf().gfx); - addTagMenu.removeAll(); - if (allowedTagTypes != null) { - for (final Class cl : allowedTagTypes) { - JMenuItem tagItem = new JMenuItem(cl.getSimpleName()); - tagItem.addActionListener(new ActionListener() { - - @Override - @SuppressWarnings("unchecked") - public void actionPerformed(ActionEvent ae) { - try { - SWF swf = folderItem.getSwf(); - Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); - t.setTimelined(swf); - swf.tags.add(t); - swf.updateCharacters(); - mainPanel.refreshTree(); - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { - Logger.getLogger(TagTree.class.getName()).log(Level.SEVERE, null, ex); - } - } - }); - addTagMenu.add(tagItem); - } - addTagMenu.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(item) > 0); - - jumpToCharacterMenuItem.setVisible(item instanceof CharacterIdTag && !(item instanceof CharacterTag)); - - rawEditMenuItem.setVisible(item instanceof Tag); + List li = new ArrayList<>(); + li.add(item); + updateContextMenu(swfs, li); } removeMenuItem.setVisible(allSelectedIsTagOrFrame); @@ -544,6 +471,114 @@ public class TagTree extends JTree implements ActionListener { }); } + public void updateContextMenu(final List swfs, List items) { + + replaceSelectionMenuItem.setVisible(false); + closeSelectionMenuItem.setVisible(false); + moveTagMenu.setVisible(false); + addTagMenu.setVisible(false); + expandRecursiveMenuItem.setVisible(false); + openSWFInsideTagMenuItem.setVisible(false); + removeMenuItem.setVisible(true); + for (TreeItem t : items) { + if (!((t instanceof Tag) || (t instanceof Frame))) { + removeMenuItem.setVisible(false); + } + } + exportSelectionMenuItem.setEnabled(!items.isEmpty() && !getSelection(items.get(0).getSwf(), items).isEmpty()); + + TreeItem item = items.get(0); + if (item instanceof ImageTag && ((ImageTag) item).importSupported()) { + replaceSelectionMenuItem.setVisible(true); + } + + if (item instanceof DefineBinaryDataTag) { + replaceSelectionMenuItem.setVisible(true); + DefineBinaryDataTag bin = (DefineBinaryDataTag) item; + if (bin.binaryData.length > 8) { + String signature = new String(bin.binaryData, 0, 3, Utf8Helper.charset); + if (Arrays.asList( + "FWS", //Uncompressed Flash + "CWS", //ZLib compressed Flash + "ZWS", //LZMA compressed Flash + "GFX", //Uncompressed ScaleForm GFx + "CFX" //Compressed ScaleForm GFx + ).contains(signature)) { + openSWFInsideTagMenuItem.setVisible(true); + } + } + } + + if (item instanceof DefineSoundTag) { + replaceSelectionMenuItem.setVisible(true); + } + + if (item instanceof SWF) { + closeSelectionMenuItem.setVisible(true); + } + + if (item instanceof FolderItem) { + final FolderItem folderItem = (FolderItem) item; + List allowedTagTypes = getTreeItemClasses(folderItem.getName(), item.getSwf().gfx); + addTagMenu.removeAll(); + if (allowedTagTypes != null) { + for (final Class cl : allowedTagTypes) { + JMenuItem tagItem = new JMenuItem(cl.getSimpleName()); + tagItem.addActionListener(new ActionListener() { + + @Override + @SuppressWarnings("unchecked") + public void actionPerformed(ActionEvent ae) { + try { + SWF swf = folderItem.getSwf(); + Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); + t.setTimelined(swf); + swf.tags.add(t); + swf.updateCharacters(); + mainPanel.refreshTree(); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { + Logger.getLogger(TagTree.class.getName()).log(Level.SEVERE, null, ex); + } + } + }); + addTagMenu.add(tagItem); + } + addTagMenu.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(item) > 0); + + jumpToCharacterMenuItem.setVisible(item instanceof CharacterIdTag && !(item instanceof CharacterTag)); + + rawEditMenuItem.setVisible(item instanceof Tag); + } + @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { @@ -657,6 +692,9 @@ public class TagTree extends JTree implements ActionListener { } public List getSelected(JTree tree) { + if (!mainPanel.folderPreviewPanel.selectedItems.isEmpty()) { + return new ArrayList<>(mainPanel.folderPreviewPanel.selectedItems.values()); + } TreeSelectionModel tsm = tree.getSelectionModel(); TreePath[] tps = tsm.getSelectionPaths(); List ret = new ArrayList<>(); @@ -672,8 +710,17 @@ public class TagTree extends JTree implements ActionListener { } public List getSelection(SWF swf) { + List sel; + if (mainPanel.folderPreviewPanel.selectedItems.isEmpty()) { + sel = getAllSelected(this); + } else { + sel = new ArrayList<>(mainPanel.folderPreviewPanel.selectedItems.values()); + } + return getSelection(swf, sel); + } + + public List getSelection(SWF swf, List sel) { List ret = new ArrayList<>(); - List sel = getAllSelected(this); for (TreeItem d : sel) { if (d.getSwf() != swf) { continue; @@ -731,6 +778,9 @@ public class TagTree extends JTree implements ActionListener { } public TreeItem getCurrentTreeItem() { + if (!mainPanel.folderPreviewPanel.selectedItems.isEmpty()) { + return mainPanel.folderPreviewPanel.selectedItems.get(0); + } TreeItem item = (TreeItem) getLastSelectedPathComponent(); return item; }