/* * Copyright (C) 2010-2013 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.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.ApplicationInfo; import com.jpexs.decompiler.flash.FrameNode; import com.jpexs.decompiler.flash.PackageNode; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.TagNode; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.console.ContextMenuTools; import com.jpexs.decompiler.flash.gui.abc.ABCPanel; import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel; import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog; import com.jpexs.decompiler.flash.gui.abc.LineMarkedEditorPane; import com.jpexs.decompiler.flash.gui.abc.TreeElement; import com.jpexs.decompiler.flash.gui.action.ActionPanel; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; import com.jpexs.decompiler.flash.gui.player.PlayerControls; import com.jpexs.decompiler.flash.helpers.Freed; import com.jpexs.decompiler.flash.tags.ABCContainerTag; 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.DoActionTag; import com.jpexs.decompiler.flash.tags.EndTag; import com.jpexs.decompiler.flash.tags.ExportAssetsTag; import com.jpexs.decompiler.flash.tags.JPEGTablesTag; import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag; import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag; import com.jpexs.decompiler.flash.tags.SymbolClassTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.VideoFrameTag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.AloneTag; import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.Container; import com.jpexs.decompiler.flash.tags.base.ContainerItem; import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; import com.jpexs.decompiler.flash.tags.text.ParseException; import com.jpexs.decompiler.flash.types.GLYPHENTRY; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.helpers.AsyncResult; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Callback; import com.jpexs.helpers.Helper; import com.jpexs.process.ProcessTools; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDropEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowStateListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.Stack; import java.util.Timer; import java.util.TimerTask; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; import javax.swing.JColorChooser; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; 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.JTextArea; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.border.BevelBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.filechooser.FileFilter; import javax.swing.plaf.basic.BasicLabelUI; import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.pushingpixels.flamingo.api.common.AbstractCommandButton; import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState; import org.pushingpixels.flamingo.api.common.CommandButtonLayoutManager; import org.pushingpixels.flamingo.api.common.JCommandButton; import org.pushingpixels.flamingo.api.common.JCommandButton.CommandButtonKind; import org.pushingpixels.flamingo.api.common.JCommandButtonPanel; import org.pushingpixels.flamingo.api.common.icon.ResizableIcon; import org.pushingpixels.flamingo.api.ribbon.JRibbon; import org.pushingpixels.flamingo.api.ribbon.JRibbonBand; import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent; import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenu; import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenuEntryFooter; import org.pushingpixels.flamingo.api.ribbon.RibbonApplicationMenuEntryPrimary; import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority; import org.pushingpixels.flamingo.api.ribbon.RibbonTask; import org.pushingpixels.flamingo.api.ribbon.resize.BaseRibbonBandResizePolicy; import org.pushingpixels.flamingo.api.ribbon.resize.CoreRibbonResizePolicies; import org.pushingpixels.flamingo.api.ribbon.resize.IconRibbonBandResizePolicy; import org.pushingpixels.flamingo.internal.ui.ribbon.AbstractBandControlPanel; import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton; /** * * @author Jindra */ public final class MainFrame extends AppRibbonFrame implements ActionListener, TreeSelectionListener, Freed { private SWF swf; public ABCPanel abcPanel; public ActionPanel actionPanel; public LoadingPanel loadingPanel = new LoadingPanel(20, 20); public JLabel statusLabel = new JLabel(""); public JPanel statusPanel = new JPanel(); public JButton cancelButton = new JButton(); public Runnable cancelButtonPressed; public JProgressBar progressBar = new JProgressBar(0, 100); private DeobfuscationDialog deobfuscationDialog; public JTree tagTree; public FlashPlayerPanel flashPanel; public JPanel displayPanel; public ImagePanel imagePanel; public ImagePanel previewImagePanel; public SWFPreviwPanel swfPreviewPanel; final static String CARDFLASHPANEL = "Flash card"; final static String CARDSWFPREVIEWPANEL = "SWF card"; final static String CARDDRAWPREVIEWPANEL = "Draw card"; final static String CARDIMAGEPANEL = "Image card"; final static String CARDEMPTYPANEL = "Empty card"; final static String CARDACTIONSCRIPTPANEL = "ActionScript card"; final static String DETAILCARDAS3NAVIGATOR = "Traits list"; final static String DETAILCARDEMPTYPANEL = "Empty card"; final static String CARDTEXTPANEL = "Text card"; final static String CARDFONTPANEL = "Font card"; private LineMarkedEditorPane textValue; private JPEGTablesTag jtt; private HashMap characters; private List abcList; JSplitPane splitPane1; JSplitPane splitPane2; private boolean splitsInited = false; private JPanel detailPanel; private JTextField filterField = new MyTextField(""); private JPanel searchPanel; private JCheckBox miAutoDeobfuscation; private JPanel displayWithPreview; private JButton textSaveButton; private JButton textEditButton; private JButton textCancelButton; private JPanel parametersPanel; private JSplitPane previewSplitPane; private JButton imageReplaceButton; private JPanel imageButtonsPanel; private JCheckBox miInternalViewer; private JCheckBox miParallelSpeedUp; private JCheckBox miAssociate; private JCheckBox miDecompile; private JCheckBox miCacheDisk; private JCheckBox miGotoMainClassOnStartup; private JLabel fontNameLabel; private JLabel fontIsBoldLabel; private JLabel fontIsItalicLabel; private JLabel fontAscentLabel; private JLabel fontDescentLabel; private JLabel fontLeadingLabel; private JTextArea fontCharactersTextArea; private JTextField fontAddCharactersField; private JButton errorNotificationButton; private ComponentListener fontChangeList; private JComboBox fontSelection; private JCommandButton saveCommandButton; private PlayerControls flashControls; private ImagePanel internelViewerPanel; private JPanel viewerCards; public static final String FLASH_VIEWER_CARD = "FLASHVIEWER"; public static final String INTERNAL_VIEWER_CARD = "INTERNALVIEWER"; private Map sourceFontsMap = new HashMap<>(); private AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); private FutureTask setSourceTask; public void setPercent(int percent) { progressBar.setValue(percent); progressBar.setVisible(true); } public void hidePercent() { if (progressBar.isVisible()) { progressBar.setVisible(false); } } static { try { File.createTempFile("temp", ".swf").delete(); //First call to this is slow, so make it first } catch (IOException ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); } } private static void addTab(JTabbedPane tabbedPane, Component tab, String title, Icon icon) { tabbedPane.add(tab); JLabel lbl = new JLabel(title); lbl.setIcon(icon); lbl.setIconTextGap(5); lbl.setHorizontalTextPosition(SwingConstants.RIGHT); tabbedPane.setTabComponentAt(tabbedPane.getTabCount() - 1, lbl); } public void setStatus(String s) { statusLabel.setText(s); } public void setWorkStatus(String s, Runnable cancelCallback) { if (s.isEmpty()) { loadingPanel.setVisible(false); } else { loadingPanel.setVisible(true); } statusLabel.setText(s); cancelButtonPressed = cancelCallback; cancelButton.setVisible(cancelCallback != null); } private String fixCommandTitle(String title) { if (title.length() > 2) { if (title.charAt(1) == ' ') { title = title.charAt(0) + "\u00A0" + title.substring(2); } } return title; } private void assignListener(JCheckBox b, final String command) { b.setActionCommand(command); b.addActionListener(this); } private void assignListener(JCommandButton b, final String command) { final MainFrame t = this; b.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { t.actionPerformed(new ActionEvent(e.getSource(), 0, command)); } }); } @SuppressWarnings("unchecked") public MainFrame(SWF swf) { super(); JRibbon rib = getRibbon(); JRibbonBand editBand = new JRibbonBand(translate("menu.general"), null); editBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(editBand.getControlPanel()), new IconRibbonBandResizePolicy(editBand.getControlPanel()))); JCommandButton openCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.open")), View.getResizableIcon("open32")); assignListener(openCommandButton, "OPEN"); saveCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.save")), View.getResizableIcon("save32")); assignListener(saveCommandButton, "SAVE"); JCommandButton saveasCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.saveas")), View.getResizableIcon("saveas16")); assignListener(saveasCommandButton, "SAVEAS"); JCommandButton reloadCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.reload")), View.getResizableIcon("reload16")); assignListener(reloadCommandButton, "RELOAD"); editBand.addCommandButton(openCommandButton, RibbonElementPriority.TOP); editBand.addCommandButton(saveCommandButton, RibbonElementPriority.TOP); editBand.addCommandButton(saveasCommandButton, RibbonElementPriority.MEDIUM); editBand.addCommandButton(reloadCommandButton, RibbonElementPriority.MEDIUM); saveCommandButton.setEnabled(!Main.readOnly); JRibbonBand exportBand = new JRibbonBand(translate("menu.export"), null); exportBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(exportBand.getControlPanel()), new IconRibbonBandResizePolicy(exportBand.getControlPanel()))); JCommandButton exportFlaCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.fla")), View.getResizableIcon("exportfla32")); assignListener(exportFlaCommandButton, "EXPORTFLA"); JCommandButton exportAllCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.all")), View.getResizableIcon("export16")); assignListener(exportAllCommandButton, "EXPORT"); JCommandButton exportSelectionCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.selection")), View.getResizableIcon("exportsel16")); assignListener(exportSelectionCommandButton, "EXPORTSEL"); exportBand.addCommandButton(exportFlaCommandButton, RibbonElementPriority.TOP); exportBand.addCommandButton(exportAllCommandButton, RibbonElementPriority.MEDIUM); exportBand.addCommandButton(exportSelectionCommandButton, RibbonElementPriority.MEDIUM); RibbonTask fileTask = new RibbonTask(translate("menu.file"), editBand, exportBand); //----------------------------------------- TOOLS ----------------------------------- JRibbonBand toolsBand = new JRibbonBand(translate("menu.tools"), null); toolsBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(toolsBand.getControlPanel()), new IconRibbonBandResizePolicy(toolsBand.getControlPanel()))); JCommandButton searchCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchas")), View.getResizableIcon("search32")); assignListener(searchCommandButton, "SEARCHAS"); JCommandButton gotoDocumentClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.gotodocumentclass")), View.getResizableIcon("gotomainclass32")); assignListener(gotoDocumentClassCommandButton, "GOTODOCUMENTCLASS"); JCommandButton proxyCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.proxy")), View.getResizableIcon("proxy16")); assignListener(proxyCommandButton, "SHOWPROXY"); JCommandButton loadMemoryCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchmemory")), View.getResizableIcon("loadmemory16")); assignListener(loadMemoryCommandButton, "LOADMEMORY"); JCommandButton loadCacheCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchcache")), View.getResizableIcon("loadcache16")); assignListener(loadCacheCommandButton, "LOADCACHE"); toolsBand.addCommandButton(searchCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(gotoDocumentClassCommandButton, RibbonElementPriority.TOP); toolsBand.addCommandButton(proxyCommandButton, RibbonElementPriority.MEDIUM); toolsBand.addCommandButton(loadMemoryCommandButton, RibbonElementPriority.MEDIUM); toolsBand.addCommandButton(loadCacheCommandButton, RibbonElementPriority.MEDIUM); if (!ProcessTools.toolsAvailable()) { loadMemoryCommandButton.setEnabled(false); } JRibbonBand deobfuscationBand = new JRibbonBand(translate("menu.tools.deobfuscation"), null); deobfuscationBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(deobfuscationBand.getControlPanel()), new IconRibbonBandResizePolicy(deobfuscationBand.getControlPanel()))); JCommandButton deobfuscationCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.pcode")), View.getResizableIcon("deobfuscate32")); assignListener(deobfuscationCommandButton, "DEOBFUSCATE"); JCommandButton globalrenameCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.globalrename")), View.getResizableIcon("rename16")); assignListener(globalrenameCommandButton, "RENAMEONEIDENTIFIER"); JCommandButton renameinvalidCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.renameinvalid")), View.getResizableIcon("renameall16")); assignListener(renameinvalidCommandButton, "RENAMEIDENTIFIERS"); deobfuscationBand.addCommandButton(deobfuscationCommandButton, RibbonElementPriority.TOP); deobfuscationBand.addCommandButton(globalrenameCommandButton, RibbonElementPriority.MEDIUM); deobfuscationBand.addCommandButton(renameinvalidCommandButton, RibbonElementPriority.MEDIUM); RibbonTask toolsTask = new RibbonTask(translate("menu.tools"), toolsBand, deobfuscationBand); //----------------------------------------- SETTINGS ----------------------------------- JRibbonBand settingsBand = new JRibbonBand(translate("menu.settings"), null); settingsBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(settingsBand.getControlPanel()), new IconRibbonBandResizePolicy(settingsBand.getControlPanel()))); miAutoDeobfuscation = new JCheckBox(translate("menu.settings.autodeobfuscation")); //assignListener(autoDeobfuscateMenuItem,"AUTODEOBFUSCATE"); miInternalViewer = new JCheckBox(translate("menu.settings.internalflashviewer")); //assignListener(miInternalViewer,"INTERNALVIEWERSWITCH"); miParallelSpeedUp = new JCheckBox(translate("menu.settings.parallelspeedup")); //assignListener(miParallelSpeedUp,"PARALLELSPEEDUP"); miDecompile = new JCheckBox(translate("menu.settings.disabledecompilation")); //assignListener(miDecompile,"DISABLEDECOMPILATION"); miAssociate = new JCheckBox(translate("menu.settings.addtocontextmenu")); //assignListener(miAssociate,"ASSOCIATE"); miCacheDisk = new JCheckBox(translate("menu.settings.cacheOnDisk")); //assignListener(miCacheDisk,"CACHEONDISK"); miGotoMainClassOnStartup = new JCheckBox(translate("menu.settings.gotoMainClassOnStartup")); //assignListener(miGotoMainClassOnStartup,"GOTODOCUMENTCLASSONSTARTUP"); settingsBand.addRibbonComponent(new JRibbonComponent(miAutoDeobfuscation)); settingsBand.addRibbonComponent(new JRibbonComponent(miInternalViewer)); settingsBand.addRibbonComponent(new JRibbonComponent(miParallelSpeedUp)); settingsBand.addRibbonComponent(new JRibbonComponent(miDecompile)); settingsBand.addRibbonComponent(new JRibbonComponent(miAssociate)); settingsBand.addRibbonComponent(new JRibbonComponent(miCacheDisk)); settingsBand.addRibbonComponent(new JRibbonComponent(miGotoMainClassOnStartup)); JRibbonBand languageBand = new JRibbonBand(translate("menu.language"), null); languageBand.setResizePolicies((List) Arrays.asList(new BaseRibbonBandResizePolicy(languageBand.getControlPanel()) { @Override public int getPreferredWidth(int i, int i1) { return 105; } @Override public void install(int i, int i1) { } }, new IconRibbonBandResizePolicy(languageBand.getControlPanel()))); JCommandButton setLanguageCommandButton = new JCommandButton(fixCommandTitle(translate("menu.settings.language")), View.getResizableIcon("setlanguage32")); assignListener(setLanguageCommandButton, "SETLANGUAGE"); languageBand.addCommandButton(setLanguageCommandButton, RibbonElementPriority.TOP); JRibbonBand advancedSettingsBand = new JRibbonBand(translate("menu.advancedsettings.advancedsettings"), null); advancedSettingsBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(advancedSettingsBand.getControlPanel()), new IconRibbonBandResizePolicy(advancedSettingsBand.getControlPanel()))); JCommandButton advancedSettingsCommandButton = new JCommandButton(fixCommandTitle(translate("menu.advancedsettings.advancedsettings")), View.getResizableIcon("settings16")); assignListener(advancedSettingsCommandButton, "ADVANCEDSETTINGS"); advancedSettingsBand.addCommandButton(advancedSettingsCommandButton, RibbonElementPriority.MEDIUM); RibbonTask settingsTask = new RibbonTask(translate("menu.settings"), settingsBand, languageBand, advancedSettingsBand); //----------------------------------------- HELP ----------------------------------- JRibbonBand helpBand = new JRibbonBand(translate("menu.help"), null); helpBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(helpBand.getControlPanel()), new IconRibbonBandResizePolicy(helpBand.getControlPanel()))); JCommandButton checkForUpdatesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.checkupdates")), View.getResizableIcon("update16")); assignListener(checkForUpdatesCommandButton, "CHECKUPDATES"); JCommandButton helpUsUpdatesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.helpus")), View.getResizableIcon("donate32")); assignListener(helpUsUpdatesCommandButton, "HELPUS"); JCommandButton homepageCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.homepage")), View.getResizableIcon("homepage16")); assignListener(homepageCommandButton, "HOMEPAGE"); JCommandButton aboutCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.about")), View.getResizableIcon("about32")); assignListener(aboutCommandButton, "ABOUT"); helpBand.addCommandButton(aboutCommandButton, RibbonElementPriority.TOP); helpBand.addCommandButton(checkForUpdatesCommandButton, RibbonElementPriority.MEDIUM); helpBand.addCommandButton(homepageCommandButton, RibbonElementPriority.MEDIUM); helpBand.addCommandButton(helpUsUpdatesCommandButton, RibbonElementPriority.TOP); RibbonTask helpTask = new RibbonTask(translate("menu.help"), helpBand); RibbonTask debugTask = null; if (Configuration.debugMode.get()) { //----------------------------------------- DEBUG ----------------------------------- JRibbonBand debugBand = new JRibbonBand("Debug", null); debugBand.setResizePolicies((List) Arrays.asList(new CoreRibbonResizePolicies.Mirror(debugBand.getControlPanel()), new IconRibbonBandResizePolicy(debugBand.getControlPanel()))); JCommandButton removeNonScriptsCommandButton = new JCommandButton(fixCommandTitle("Remove non scripts"), View.getResizableIcon("update16")); assignListener(removeNonScriptsCommandButton, "REMOVENONSCRIPTS"); JCommandButton refreshDecompiledCommandButton = new JCommandButton(fixCommandTitle("Refresh decompiled script"), View.getResizableIcon("update16")); assignListener(refreshDecompiledCommandButton, "REFRESHDECOMPILED"); debugBand.addCommandButton(removeNonScriptsCommandButton, RibbonElementPriority.MEDIUM); debugBand.addCommandButton(refreshDecompiledCommandButton, RibbonElementPriority.MEDIUM); debugTask = new RibbonTask("Debug", debugBand); } rib.addTask(fileTask); rib.addTask(toolsTask); rib.addTask(settingsTask); rib.addTask(helpTask); if (debugTask != null) { rib.addTask(debugTask); } RibbonApplicationMenu mainMenu = new RibbonApplicationMenu(); RibbonApplicationMenuEntryPrimary exportFlaMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("exportfla32"), translate("menu.file.export.fla"), new ActionRedirector(this, "EXPORTFLA"), CommandButtonKind.ACTION_ONLY); RibbonApplicationMenuEntryPrimary exportAllMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("export32"), translate("menu.file.export.all"), new ActionRedirector(this, "EXPORTSEL"), CommandButtonKind.ACTION_ONLY); RibbonApplicationMenuEntryPrimary exportSelMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("exportsel32"), translate("menu.file.export.selection"), new ActionRedirector(this, "EXPORTSEL"), CommandButtonKind.ACTION_ONLY); RibbonApplicationMenuEntryPrimary checkUpdatesMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("update32"), translate("menu.help.checkupdates"), new ActionRedirector(this, "CHECKUPDATES"), CommandButtonKind.ACTION_ONLY); RibbonApplicationMenuEntryPrimary aboutMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("about32"), translate("menu.help.about"), new ActionRedirector(this, "ABOUT"), CommandButtonKind.ACTION_ONLY); RibbonApplicationMenuEntryPrimary openFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("open32"), translate("menu.file.open"), new ActionRedirector(this, "OPEN"), CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION); openFileMenu.setRolloverCallback(new RibbonApplicationMenuEntryPrimary.PrimaryRolloverCallback() { @Override public void menuEntryActivated(JPanel targetPanel) { targetPanel.removeAll(); JCommandButtonPanel openHistoryPanel = new JCommandButtonPanel(CommandButtonDisplayState.MEDIUM); String groupName = translate("menu.recentFiles"); openHistoryPanel.addButtonGroup(groupName); List recentFiles = Configuration.getRecentFiles(); int j = 0; for (int i = recentFiles.size() - 1; i >= 0; i--) { String path = recentFiles.get(i); RecentFilesButton historyButton = new RecentFilesButton(j + " " + path, null); historyButton.fileName = path; historyButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { RecentFilesButton source = (RecentFilesButton) ae.getSource(); Main.openFile(source.fileName); } }); j++; historyButton.setHorizontalAlignment(SwingUtilities.LEFT); openHistoryPanel.addButtonToLastGroup(historyButton); } openHistoryPanel.setMaxButtonColumns(1); targetPanel.setLayout(new BorderLayout()); targetPanel.add(openHistoryPanel, BorderLayout.CENTER); } }); RibbonApplicationMenuEntryFooter exitMenu = new RibbonApplicationMenuEntryFooter(View.getResizableIcon("exit32"), translate("menu.file.exit"), new ActionRedirector(this, "EXIT")); mainMenu.addMenuEntry(openFileMenu); mainMenu.addMenuSeparator(); mainMenu.addMenuEntry(exportFlaMenu); mainMenu.addMenuEntry(exportAllMenu); mainMenu.addMenuEntry(exportSelMenu); mainMenu.addMenuSeparator(); mainMenu.addMenuEntry(checkUpdatesMenu); mainMenu.addMenuEntry(aboutMenu); mainMenu.addFooterEntry(exitMenu); mainMenu.addMenuSeparator(); rib.setApplicationMenu(mainMenu); int w = Configuration.guiWindowWidth.get(); int h = Configuration.guiWindowHeight.get(); Dimension dim = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); if (w > dim.width) { w = dim.width; } if (h > dim.height) { h = dim.height; } setSize(w, h); boolean maximizedHorizontal = Configuration.guiWindowMaximizedHorizontal.get(); boolean maximizedVertical = Configuration.guiWindowMaximizedVertical.get(); int state = 0; if (maximizedHorizontal) { state |= JFrame.MAXIMIZED_HORIZ; } if (maximizedVertical) { state |= JFrame.MAXIMIZED_VERT; } setExtendedState(state); View.setWindowIcon(this); addWindowStateListener(new WindowStateListener() { @Override public void windowStateChanged(WindowEvent e) { int state = e.getNewState(); Configuration.guiWindowMaximizedHorizontal.set((state & JFrame.MAXIMIZED_HORIZ) == JFrame.MAXIMIZED_HORIZ); Configuration.guiWindowMaximizedVertical.set((state & JFrame.MAXIMIZED_VERT) == JFrame.MAXIMIZED_VERT); } }); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { int state = getExtendedState(); if ((state & JFrame.MAXIMIZED_HORIZ) == 0) { Configuration.guiWindowWidth.set(getWidth()); } if ((state & JFrame.MAXIMIZED_VERT) == 0) { Configuration.guiWindowHeight.set(getHeight()); } } }); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (Main.proxyFrame != null) { if (Main.proxyFrame.isVisible()) { return; } } if (Main.loadFromMemoryFrame != null) { if (Main.loadFromMemoryFrame.isVisible()) { return; } } if (Main.loadFromCacheFrame != null) { if (Main.loadFromCacheFrame.isVisible()) { return; } } Main.exit(); } }); setTitle(ApplicationInfo.applicationVerName + ((swf != null && Configuration.displayFileName.get()) ? " - " + Main.getFileTitle() : "")); JMenuBar menuBar = new JMenuBar(); try { flashPanel = new FlashPlayerPanel(this); } catch (FlashUnsupportedException fue) { } JMenu menuFile = new JMenu(translate("menu.file")); JMenuItem miOpen = new JMenuItem(translate("menu.file.open")); miOpen.setIcon(View.getIcon("open16")); miOpen.setActionCommand("OPEN"); miOpen.addActionListener(this); JMenuItem miSave = new JMenuItem(translate("menu.file.save")); miSave.setIcon(View.getIcon("save16")); miSave.setActionCommand("SAVE"); miSave.addActionListener(this); JMenuItem miSaveAs = new JMenuItem(translate("menu.file.saveas")); miSaveAs.setIcon(View.getIcon("saveas16")); miSaveAs.setActionCommand("SAVEAS"); miSaveAs.addActionListener(this); JMenuItem menuExportFla = new JMenuItem(translate("menu.file.export.fla")); menuExportFla.setActionCommand("EXPORTFLA"); menuExportFla.addActionListener(this); menuExportFla.setIcon(View.getIcon("flash16")); JMenuItem menuExportAll = new JMenuItem(translate("menu.file.export.all")); menuExportAll.setActionCommand("EXPORT"); menuExportAll.addActionListener(this); JMenuItem menuExportSel = new JMenuItem(translate("menu.file.export.selection")); menuExportSel.setActionCommand("EXPORTSEL"); menuExportSel.addActionListener(this); menuExportAll.setIcon(View.getIcon("export16")); menuExportSel.setIcon(View.getIcon("exportsel16")); menuFile.add(miOpen); menuFile.add(miSave); menuFile.add(miSaveAs); menuFile.add(menuExportFla); menuFile.add(menuExportAll); menuFile.add(menuExportSel); menuFile.addSeparator(); JMenuItem miClose = new JMenuItem(translate("menu.file.exit")); miClose.setIcon(View.getIcon("exit16")); miClose.setActionCommand("EXIT"); miClose.addActionListener(this); menuFile.add(miClose); menuBar.add(menuFile); JMenu menuDeobfuscation = new JMenu(translate("menu.tools.deobfuscation")); menuDeobfuscation.setIcon(View.getIcon("deobfuscate16")); JMenuItem miDeobfuscation = new JMenuItem(translate("menu.tools.deobfuscation.pcode")); miDeobfuscation.setActionCommand("DEOBFUSCATE"); miDeobfuscation.addActionListener(this); //autoDeobfuscateMenuItem = new JCheckBoxMenuItem(translate("menu.settings.autodeobfuscation")); miAutoDeobfuscation.setSelected(Configuration.autoDeobfuscate.get()); miAutoDeobfuscation.addActionListener(this); miAutoDeobfuscation.setActionCommand("AUTODEOBFUSCATE"); JMenuItem miRenameOneIdentifier = new JMenuItem(translate("menu.tools.deobfuscation.globalrename")); miRenameOneIdentifier.setActionCommand("RENAMEONEIDENTIFIER"); miRenameOneIdentifier.addActionListener(this); JMenuItem miRenameIdentifiers = new JMenuItem(translate("menu.tools.deobfuscation.renameinvalid")); miRenameIdentifiers.setActionCommand("RENAMEIDENTIFIERS"); miRenameIdentifiers.addActionListener(this); menuDeobfuscation.add(miRenameOneIdentifier); menuDeobfuscation.add(miRenameIdentifiers); menuDeobfuscation.add(miDeobfuscation); JMenu menuTools = new JMenu(translate("menu.tools")); JMenuItem miProxy = new JMenuItem(translate("menu.tools.proxy")); miProxy.setActionCommand("SHOWPROXY"); miProxy.setIcon(View.getIcon("proxy16")); miProxy.addActionListener(this); JMenuItem miSearchScript = new JMenuItem(translate("menu.tools.searchas")); miSearchScript.addActionListener(this); miSearchScript.setActionCommand("SEARCHAS"); miSearchScript.setIcon(View.getIcon("search16")); menuTools.add(miSearchScript); //miInternalViewer = new JCheckBox(translate("menu.settings.internalflashviewer")); boolean externalFlashPlayerUnavailable = flashPanel == null; miInternalViewer.setSelected(Configuration.internalFlashViewer.get() || externalFlashPlayerUnavailable); if (externalFlashPlayerUnavailable) { miInternalViewer.setEnabled(false); } miInternalViewer.setActionCommand("INTERNALVIEWERSWITCH"); miInternalViewer.addActionListener(this); //miParallelSpeedUp = new JCheckBox(translate("menu.settings.parallelspeedup")); miParallelSpeedUp.setSelected(Configuration.parallelSpeedUp.get()); miParallelSpeedUp.setActionCommand("PARALLELSPEEDUP"); miParallelSpeedUp.addActionListener(this); menuTools.add(miProxy); //menuTools.add(menuDeobfuscation); menuTools.add(menuDeobfuscation); JMenuItem miGotoDocumentClass = new JMenuItem(translate("menu.tools.gotodocumentclass")); miGotoDocumentClass.setActionCommand("GOTODOCUMENTCLASS"); miGotoDocumentClass.addActionListener(this); menuBar.add(menuTools); //miDecompile = new JCheckBox(translate("menu.settings.disabledecompilation")); miDecompile.setSelected(!Configuration.decompile.get()); miDecompile.setActionCommand("DISABLEDECOMPILATION"); miDecompile.addActionListener(this); //miCacheDisk = new JCheckBox(translate("menu.settings.cacheOnDisk")); miCacheDisk.setSelected(Configuration.cacheOnDisk.get()); miCacheDisk.setActionCommand("CACHEONDISK"); miCacheDisk.addActionListener(this); // miGotoMainClassOnStartup = new JCheckBox(translate("menu.settings.gotoMainClassOnStartup")); miGotoMainClassOnStartup.setSelected(Configuration.gotoMainClassOnStartup.get()); miGotoMainClassOnStartup.setActionCommand("GOTODOCUMENTCLASSONSTARTUP"); miGotoMainClassOnStartup.addActionListener(this); /*JMenu menuSettings = new JMenu(translate("menu.settings")); menuSettings.add(autoDeobfuscateMenuItem); menuSettings.add(miInternalViewer); menuSettings.add(miParallelSpeedUp); menuSettings.add(miDecompile); menuSettings.add(miCacheDisk); menuSettings.add(miGotoMainClassOnStartup);*/ // miAssociate = new JCheckBox(translate("menu.settings.addtocontextmenu")); miAssociate.setActionCommand("ASSOCIATE"); miAssociate.addActionListener(this); miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu()); JMenuItem miLanguage = new JMenuItem(translate("menu.settings.language")); miLanguage.setActionCommand("SETLANGUAGE"); miLanguage.addActionListener(this); /* if (Platform.isWindows()) { menuSettings.add(miAssociate); } menuSettings.add(miLanguage); menuBar.add(menuSettings);*/ JMenu menuHelp = new JMenu(translate("menu.help")); JMenuItem miAbout = new JMenuItem(translate("menu.help.about")); miAbout.setIcon(View.getIcon("about16")); miAbout.setActionCommand("ABOUT"); miAbout.addActionListener(this); JMenuItem miCheckUpdates = new JMenuItem(translate("menu.help.checkupdates")); miCheckUpdates.setActionCommand("CHECKUPDATES"); miCheckUpdates.setIcon(View.getIcon("update16")); miCheckUpdates.addActionListener(this); JMenuItem miHelpUs = new JMenuItem(translate("menu.help.helpus")); miHelpUs.setActionCommand("HELPUS"); miHelpUs.setIcon(View.getIcon("donate16")); miHelpUs.addActionListener(this); JMenuItem miHomepage = new JMenuItem(translate("menu.help.homepage")); miHomepage.setActionCommand("HOMEPAGE"); miHomepage.setIcon(View.getIcon("homepage16")); miHomepage.addActionListener(this); menuHelp.add(miCheckUpdates); menuHelp.add(miHelpUs); menuHelp.add(miHomepage); menuHelp.add(miAbout); menuBar.add(menuHelp); //setJMenuBar(menuBar); List objs = new ArrayList<>(); if (swf != null) { objs.addAll(swf.tags); } this.swf = swf; java.awt.Container cnt = getContentPane(); cnt.setLayout(new BorderLayout()); cnt.add(getRibbon(), BorderLayout.NORTH); detailPanel = new JPanel(); detailPanel.setLayout(new CardLayout()); JPanel whitePanel = new JPanel(); whitePanel.setBackground(Color.white); detailPanel.add(whitePanel, DETAILCARDEMPTYPANEL); CardLayout cl2 = (CardLayout) (detailPanel.getLayout()); cl2.show(detailPanel, DETAILCARDEMPTYPANEL); abcList = new ArrayList<>(); getActionScript3(objs, abcList); if (!abcList.isEmpty()) { abcPanel = new ABCPanel(abcList, swf); detailPanel.add(abcPanel.tabbedPane, DETAILCARDAS3NAVIGATOR); menuTools.add(miGotoDocumentClass); } else { gotoDocumentClassCommandButton.setEnabled(false); actionPanel = new ActionPanel(); deobfuscationCommandButton.setEnabled(false); //miDeobfuscation.setEnabled(false); } if (swf == null) { renameinvalidCommandButton.setEnabled(false); globalrenameCommandButton.setEnabled(false); saveCommandButton.setEnabled(false); saveasCommandButton.setEnabled(false); exportAllCommandButton.setEnabled(false); exportAllMenu.setEnabled(false); exportFlaCommandButton.setEnabled(false); exportFlaMenu.setEnabled(false); exportSelectionCommandButton.setEnabled(false); exportSelMenu.setEnabled(false); deobfuscationCommandButton.setEnabled(false); searchCommandButton.setEnabled(false); reloadCommandButton.setEnabled(false); } UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName()); if (swf == null) { tagTree = new JTree((TreeModel) null); } else { tagTree = new JTree(new TagTreeModel(createTagList(objs, null), new SWFRoot((new File(Main.file)).getName()))); } tagTree.addTreeSelectionListener(this); tagTree.setBackground(Color.white); tagTree.setUI(new BasicTreeUI() { @Override public void paint(Graphics g, JComponent c) { setHashColor(Color.gray); super.paint(g, c); } }); DragSource dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer(tagTree, DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener() { @Override public void dragGestureRecognized(DragGestureEvent dge) { dge.startDrag(DragSource.DefaultCopyDrop, new Transferable() { @Override public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.javaFileListFlavor}; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(DataFlavor.javaFileListFlavor); } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (flavor.equals(DataFlavor.javaFileListFlavor)) { List files = new ArrayList<>(); String tempDir = System.getProperty("java.io.tmpdir"); if (!tempDir.endsWith(File.separator)) { tempDir += File.separator; } Random rnd = new Random(); tempDir += "ffdec" + File.separator + "export" + File.separator + System.currentTimeMillis() + "_" + rnd.nextInt(1000); File fTempDir = new File(tempDir); if (!fTempDir.exists()) { if (!fTempDir.mkdirs()) { if (!fTempDir.exists()) { throw new IOException("cannot create directory " + fTempDir); } } } final ExportDialog export = new ExportDialog(); try { File ftemp = new File(tempDir); files = exportSelection(errorHandler, tempDir, export); files.clear(); File[] fs = ftemp.listFiles(); files.addAll(Arrays.asList(fs)); Main.stopWork(); } catch (IOException ex) { return null; } for (File f : files) { f.deleteOnExit(); } new File(tempDir).deleteOnExit(); return files; } return null; } }, new DragSourceListener() { @Override public void dragEnter(DragSourceDragEvent dsde) { enableDrop(false); } @Override public void dragOver(DragSourceDragEvent dsde) { } @Override public void dropActionChanged(DragSourceDragEvent dsde) { } @Override public void dragExit(DragSourceEvent dse) { } @Override public void dragDropEnd(DragSourceDropEvent dsde) { enableDrop(true); } }); } }); final JPopupMenu contextPopupMenu = new JPopupMenu(); final JMenuItem removeMenuItem = new JMenuItem(translate("contextmenu.remove")); removeMenuItem.addActionListener(this); removeMenuItem.setActionCommand("REMOVEITEM"); JMenuItem exportSelectionMenuItem = new JMenuItem(translate("menu.file.export.selection")); exportSelectionMenuItem.setActionCommand("EXPORTSEL"); exportSelectionMenuItem.addActionListener(this); contextPopupMenu.add(exportSelectionMenuItem); contextPopupMenu.add(removeMenuItem); 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 allSelectedIsTag = true; for (TreePath treePath : paths) { Object tagObj = treePath.getLastPathComponent(); if (tagObj instanceof TagNode) { Object tag = ((TagNode) tagObj).tag; if (!(tag instanceof Tag)) { allSelectedIsTag = false; break; } } } removeMenuItem.setVisible(allSelectedIsTag); contextPopupMenu.show(e.getComponent(), e.getX(), e.getY()); } } }); TreeCellRenderer tcr = new 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); Object val = value; if (val instanceof TagNode) { val = ((TagNode) val).tag; } String type = getTagType(val); if (row == 0) { setIcon(View.getIcon("flash16")); } else if (type != null) { if (type.equals("folder") && expanded) { type = "folderopen"; } setIcon(View.getIcon(type + "16")); //setToolTipText("This book is in the Tutorial series."); } else { //setToolTipText(null); //no tool tip } String tos = value.toString(); int sw = getFontMetrics(getFont()).stringWidth(tos); setPreferredSize(new Dimension(18 + sw, getPreferredSize().height)); setUI(new BasicLabelUI()); setOpaque(false); //setBackground(Color.green); setBackgroundNonSelectionColor(Color.white); //setBackgroundSelectionColor(Color.ORANGE); return this; } }; tagTree.setCellRenderer(tcr); JPanel statusLeftPanel = new JPanel(); statusLeftPanel.setLayout(new BoxLayout(statusLeftPanel, BoxLayout.X_AXIS)); loadingPanel.setPreferredSize(new Dimension(30, 30)); // todo: this button is a little bit ugly in the UI. Maybe it can be changed to an icon (as in NetBeans) cancelButton.setText(translate("button.cancel")); cancelButton.setPreferredSize(new Dimension(100, 30)); cancelButton.setBorderPainted(false); cancelButton.setOpaque(false); cancelButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (cancelButtonPressed != null) { cancelButtonPressed.run(); } } }); statusLeftPanel.add(loadingPanel); statusLeftPanel.add(statusLabel); statusLeftPanel.add(cancelButton); statusPanel = new JPanel(); statusPanel.setPreferredSize(new Dimension(1, 30)); statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED)); statusPanel.setLayout(new BorderLayout()); statusPanel.add(statusLeftPanel, BorderLayout.WEST); errorNotificationButton = new JButton(""); errorNotificationButton.setIcon(View.getIcon("okay16")); errorNotificationButton.setBorderPainted(false); errorNotificationButton.setFocusPainted(false); errorNotificationButton.setContentAreaFilled(false); errorNotificationButton.setMargin(new Insets(2, 2, 2, 2)); errorNotificationButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); errorNotificationButton.setActionCommand("SHOWERRORLOG"); errorNotificationButton.addActionListener(this); errorNotificationButton.setToolTipText(translate("errors.none")); statusPanel.add(errorNotificationButton, BorderLayout.EAST); loadingPanel.setVisible(false); cancelButton.setVisible(false); cnt.add(statusPanel, BorderLayout.SOUTH); if (swf != null) { for (Tag t : swf.tags) { if (t instanceof JPEGTablesTag) { jtt = (JPEGTablesTag) t; } } } characters = new HashMap<>(); List list2 = new ArrayList<>(); if (swf != null) { list2.addAll(swf.tags); } parseCharacters(list2); JPanel textTopPanel = new JPanel(new BorderLayout()); textValue = new LineMarkedEditorPane(); textTopPanel.add(new JScrollPane(textValue), BorderLayout.CENTER); textValue.setEditable(false); //textValue.setFont(UIManager.getFont("TextField.font")); JPanel textButtonsPanel = new JPanel(); textButtonsPanel.setLayout(new FlowLayout()); textSaveButton = new JButton(translate("button.save"), View.getIcon("save16")); textSaveButton.setMargin(new Insets(3, 3, 3, 10)); textSaveButton.setActionCommand("SAVETEXT"); textSaveButton.addActionListener(this); textEditButton = new JButton(translate("button.edit"), View.getIcon("edit16")); textEditButton.setMargin(new Insets(3, 3, 3, 10)); textEditButton.setActionCommand("EDITTEXT"); textEditButton.addActionListener(this); textCancelButton = new JButton(translate("button.cancel"), View.getIcon("cancel16")); textCancelButton.setMargin(new Insets(3, 3, 3, 10)); textCancelButton.setActionCommand("CANCELTEXT"); textCancelButton.addActionListener(this); textButtonsPanel.add(textEditButton); textButtonsPanel.add(textSaveButton); textButtonsPanel.add(textCancelButton); textSaveButton.setVisible(false); textCancelButton.setVisible(false); textTopPanel.add(textButtonsPanel, BorderLayout.SOUTH); displayWithPreview = new JPanel(new CardLayout()); displayWithPreview.add(textTopPanel, CARDTEXTPANEL); //TODO: This layout SUCKS! If you know something better, please fix it! final JPanel fontPanel = new JPanel(); final JPanel fontParams2 = new JPanel(); fontParams2.setLayout(null); final Component[][] ctable = new Component[][]{ {new JLabel(translate("font.name")), fontNameLabel = new JLabel(translate("value.unknown"))}, {new JLabel(translate("font.isbold")), fontIsBoldLabel = new JLabel(translate("value.unknown"))}, {new JLabel(translate("font.isitalic")), fontIsItalicLabel = new JLabel(translate("value.unknown"))}, {new JLabel(translate("font.ascent")), fontAscentLabel = new JLabel(translate("value.unknown"))}, {new JLabel(translate("font.descent")), fontDescentLabel = new JLabel(translate("value.unknown"))}, {new JLabel(translate("font.leading")), fontLeadingLabel = new JLabel(translate("value.unknown"))}, {new JLabel(translate("font.characters")), fontCharactersTextArea = new JTextArea("")} }; fontCharactersTextArea.setLineWrap(true); fontCharactersTextArea.setWrapStyleWord(true); fontCharactersTextArea.setOpaque(false); fontCharactersTextArea.setEditable(false); fontCharactersTextArea.setFont(new JLabel().getFont()); final int borderLeft = 10; final int[] maxws = new int[ctable[0].length]; for (int x = 0; x < ctable[0].length; x++) { int maxw = 0; for (int y = 0; y < ctable.length; y++) { Dimension d = ctable[y][x].getPreferredSize(); if (d.width > maxw) { maxw = d.width; } } maxws[x] = maxw; } for (int i = 0; i < ctable.length; i++) { fontParams2.add(ctable[i][0]); fontParams2.add(ctable[i][1]); } //fontParams2.setPreferredSize(new Dimension(600, ctable.length * 25)); fontChangeList = new ComponentListener() { @Override public void componentResized(ComponentEvent e) { int h = 0; Insets is = fontPanel.getInsets(); Insets is2 = fontParams2.getInsets(); for (int i = 0; i < ctable.length; i++) { Dimension d = ctable[i][0].getPreferredSize(); Dimension d2 = ctable[i][1].getPreferredSize(); ctable[i][0].setBounds(borderLeft, h, maxws[0], d2.height); int w2 = fontPanel.getWidth() - 3 * borderLeft - maxws[0] - is.left - is.right - 10; ctable[i][1].setBounds(borderLeft + maxws[0] + borderLeft, h, w2, d2.height); h += Math.max(d.height, d2.height); } fontParams2.setPreferredSize(new Dimension(fontPanel.getWidth() - 20, h)); fontPanel.revalidate(); } @Override public void componentMoved(ComponentEvent e) { componentResized(null); } @Override public void componentShown(ComponentEvent e) { componentResized(null); } @Override public void componentHidden(ComponentEvent e) { componentResized(null); } }; final JPanel fontParams1 = new JPanel(); fontPanel.addComponentListener(fontChangeList); fontChangeList.componentResized(null); fontParams1.setLayout(new BoxLayout(fontParams1, BoxLayout.Y_AXIS)); fontParams1.add(fontParams2); JPanel fontAddCharsPanel = new JPanel(new FlowLayout()); fontAddCharsPanel.add(new JLabel(translate("font.characters.add"))); fontAddCharactersField = new MyTextField(); fontAddCharactersField.setPreferredSize(new Dimension(150, fontAddCharactersField.getPreferredSize().height)); fontAddCharsPanel.add(fontAddCharactersField); JButton fontAddCharsButton = new JButton(translate("button.ok")); fontAddCharsButton.setActionCommand("FONTADDCHARS"); fontAddCharsButton.addActionListener(this); fontAddCharsPanel.add(fontAddCharsButton); JButton fontEmbedButton = new JButton(translate("button.font.embed")); fontEmbedButton.setActionCommand("FONTEMBED"); fontEmbedButton.addActionListener(this); //fontAddCharsPanel.add(fontEmbedButton); fontParams1.add(fontAddCharsPanel); JPanel fontSelectionPanel = new JPanel(new FlowLayout()); fontSelectionPanel.add(new JLabel(translate("font.source"))); fontSelection = new JComboBox<>(FontTag.fontNames.toArray(new String[FontTag.fontNames.size()])); fontSelection.setSelectedIndex(0); fontSelection.setSelectedItem("Times New Roman"); fontSelection.setSelectedItem("Arial"); fontSelection.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (oldValue instanceof FontTag) { FontTag f = (FontTag) oldValue; sourceFontsMap.put(f.getFontId(), (String) fontSelection.getSelectedItem()); } } }); fontSelectionPanel.add(fontSelection); JPanel fontCharPanel = new JPanel(); fontCharPanel.setLayout(new ListLayout()); fontCharPanel.add(fontAddCharsPanel); fontCharPanel.add(fontSelectionPanel); fontParams1.add(fontCharPanel); fontParams1.add(fontEmbedButton); fontPanel.setLayout(new BorderLayout()); fontParams1.add(Box.createVerticalGlue()); fontPanel.add(new JScrollPane(fontParams1), BorderLayout.CENTER); displayWithPreview.add(fontPanel, CARDFONTPANEL); Component leftComponent = null; displayPanel = new JPanel(new CardLayout()); if (flashPanel != null) { JPanel flashPlayPanel = new JPanel(new BorderLayout()); flashPlayPanel.add(flashPanel, BorderLayout.CENTER); flashPlayPanel.add(flashControls = new PlayerControls(flashPanel), BorderLayout.SOUTH); leftComponent = flashPlayPanel; } else { JPanel swtPanel = new JPanel(new BorderLayout()); swtPanel.add(new JLabel("
" + translate("notavailonthisplatform") + "
", JLabel.CENTER), BorderLayout.CENTER); swtPanel.setBackground(View.DEFAULT_BACKGROUND_COLOR); leftComponent = swtPanel; } textValue.setContentType("text/swf_text"); previewSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); previewSplitPane.setDividerLocation(300); JPanel pan = new JPanel(new BorderLayout()); JLabel prevLabel = new HeaderLabel(translate("swfpreview")); prevLabel.setHorizontalAlignment(SwingConstants.CENTER); //prevLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); JLabel paramsLabel = new HeaderLabel(translate("parameters")); paramsLabel.setHorizontalAlignment(SwingConstants.CENTER); //paramsLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); pan.add(prevLabel, BorderLayout.NORTH); viewerCards = new JPanel(); viewerCards.setLayout(new CardLayout()); //viewerCards.add(leftComponent,FLASH_VIEWER_CARD); internelViewerPanel = new ImagePanel(); JPanel ivPanel = new JPanel(new BorderLayout()); ivPanel.add(new HeaderLabel(translate("swfpreview.internal")), BorderLayout.NORTH); ivPanel.add(internelViewerPanel, BorderLayout.CENTER); viewerCards.add(ivPanel, INTERNAL_VIEWER_CARD); ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); if (flashPanel != null) { JPanel bottomPanel = new JPanel(new BorderLayout()); JPanel buttonsPanel = new JPanel(new FlowLayout()); JButton selectColorButton = new JButton(View.getIcon("color16")); selectColorButton.addActionListener(this); selectColorButton.setActionCommand("SELECTCOLOR"); selectColorButton.setToolTipText(AppStrings.translate("button.selectcolor.hint")); buttonsPanel.add(selectColorButton); bottomPanel.add(buttonsPanel, BorderLayout.EAST); pan.add(bottomPanel, BorderLayout.SOUTH); } pan.add(leftComponent, BorderLayout.CENTER); viewerCards.add(pan, FLASH_VIEWER_CARD); previewSplitPane.setLeftComponent(viewerCards); parametersPanel = new JPanel(new BorderLayout()); parametersPanel.add(paramsLabel, BorderLayout.NORTH); parametersPanel.add(displayWithPreview, BorderLayout.CENTER); previewSplitPane.setRightComponent(parametersPanel); parametersPanel.setVisible(false); displayPanel.add(previewSplitPane, CARDFLASHPANEL); imagePanel = new ImagePanel(); JPanel imagesCard = new JPanel(new BorderLayout()); imagesCard.add(imagePanel, BorderLayout.CENTER); imageReplaceButton = new JButton(translate("button.replace"), View.getIcon("edit16")); imageReplaceButton.setMargin(new Insets(3, 3, 3, 10)); imageReplaceButton.setActionCommand("REPLACEIMAGE"); imageReplaceButton.addActionListener(this); imageButtonsPanel = new JPanel(new FlowLayout()); imageButtonsPanel.add(imageReplaceButton); imagesCard.add(imageButtonsPanel, BorderLayout.SOUTH); displayPanel.add(imagesCard, CARDIMAGEPANEL); JPanel shapesCard = new JPanel(new BorderLayout()); JPanel previewPanel = new JPanel(new BorderLayout()); previewImagePanel = new ImagePanel(); JPanel previewCnt = new JPanel(new BorderLayout()); previewCnt.add(previewImagePanel, BorderLayout.CENTER); previewCnt.add(new PlayerControls(previewImagePanel), BorderLayout.SOUTH); previewPanel.add(previewCnt, BorderLayout.CENTER); JLabel prevIntLabel = new HeaderLabel(translate("swfpreview.internal")); prevIntLabel.setHorizontalAlignment(SwingConstants.CENTER); //prevIntLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); previewPanel.add(prevIntLabel, BorderLayout.NORTH); shapesCard.add(previewPanel, BorderLayout.CENTER); displayPanel.add(shapesCard, CARDDRAWPREVIEWPANEL); swfPreviewPanel = new SWFPreviwPanel(); displayPanel.add(swfPreviewPanel, CARDSWFPREVIEWPANEL); displayPanel.add(new JPanel(), CARDEMPTYPANEL); if (actionPanel != null) { displayPanel.add(actionPanel, CARDACTIONSCRIPTPANEL); } if (abcPanel != null) { displayPanel.add(abcPanel, CARDACTIONSCRIPTPANEL); } CardLayout cl = (CardLayout) (displayPanel.getLayout()); cl.show(displayPanel, CARDEMPTYPANEL); searchPanel = new JPanel(); searchPanel.setLayout(new BorderLayout()); searchPanel.add(filterField, BorderLayout.CENTER); searchPanel.add(new JLabel(View.getIcon("search16")), BorderLayout.WEST); JLabel closeSearchButton = new JLabel(View.getIcon("cancel16")); closeSearchButton.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { filterField.setText(""); doFilter(); searchPanel.setVisible(false); } }); searchPanel.add(closeSearchButton, BorderLayout.EAST); JPanel pan1 = new JPanel(new BorderLayout()); pan1.add(new JScrollPane(tagTree), BorderLayout.CENTER); pan1.add(searchPanel, BorderLayout.SOUTH); filterField.setActionCommand("FILTERSCRIPT"); filterField.addActionListener(this); searchPanel.setVisible(false); filterField.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) { warn(); } @Override public void removeUpdate(DocumentEvent e) { warn(); } @Override public void insertUpdate(DocumentEvent e) { warn(); } public void warn() { doFilter(); } }); //displayPanel.setBorder(BorderFactory.createLineBorder(Color.black)); splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pan1, detailPanel); splitPane1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, splitPane2, displayPanel); if (swf == null) { JPanel welcomePanel = new JPanel(); welcomePanel.setLayout(new BoxLayout(welcomePanel, BoxLayout.Y_AXIS)); JLabel welcomeToLabel = new JLabel(translate("startup.welcometo")); welcomeToLabel.setFont(welcomeToLabel.getFont().deriveFont(40)); welcomeToLabel.setAlignmentX(0.5f); JPanel appNamePanel = new JPanel(new FlowLayout()); JLabel jpLabel = new JLabel("JPEXS "); jpLabel.setAlignmentX(0.5f); jpLabel.setForeground(new Color(0, 0, 160)); jpLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); jpLabel.setHorizontalAlignment(SwingConstants.CENTER); appNamePanel.add(jpLabel); JLabel ffLabel = new JLabel("Free Flash "); ffLabel.setAlignmentX(0.5f); ffLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); ffLabel.setHorizontalAlignment(SwingConstants.CENTER); appNamePanel.add(ffLabel); JLabel decLabel = new JLabel("Decompiler"); decLabel.setAlignmentX(0.5f); decLabel.setForeground(Color.red); decLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); decLabel.setHorizontalAlignment(SwingConstants.CENTER); appNamePanel.add(decLabel); appNamePanel.setAlignmentX(0.5f); welcomePanel.add(Box.createGlue()); welcomePanel.add(welcomeToLabel); welcomePanel.add(appNamePanel); JLabel startLabel = new JLabel(translate("startup.selectopen")); startLabel.setAlignmentX(0.5f); startLabel.setFont(startLabel.getFont().deriveFont(30)); welcomePanel.add(startLabel); welcomePanel.add(Box.createGlue()); cnt.add(welcomePanel, BorderLayout.CENTER); actionPanel = null; abcPanel = null; } else { cnt.add(splitPane1, BorderLayout.CENTER); } //splitPane1.setDividerLocation(0.5); splitPane1.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pce) { if (splitsInited) { Configuration.guiSplitPane1DividerLocation.set((int) pce.getNewValue()); } } }); splitPane2.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent pce) { if (detailPanel.isVisible()) { Configuration.guiSplitPane2DividerLocation.set((int) pce.getNewValue()); } } }); View.centerScreen(this); tagTree.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if ((e.getKeyCode() == 'F') && (e.isControlDown())) { searchPanel.setVisible(true); filterField.requestFocusInWindow(); } } }); detailPanel.setVisible(false); //Opening files with drag&drop to main window enableDrop(true); } public void enableDrop(boolean value) { if (value) { setDropTarget(new DropTarget() { @Override public synchronized void drop(DropTargetDropEvent dtde) { try { dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); @SuppressWarnings("unchecked") List droppedFiles = (List) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); if (!droppedFiles.isEmpty()) { Main.openFile(droppedFiles.get(0).getAbsolutePath()); } } catch (UnsupportedFlavorException | IOException ex) { } } }); } else { setDropTarget(null); } } public void doFilter() { TagNode n = getASTagNode(tagTree); if (n != null) { if (n.tag instanceof ClassesListTreeModel) { n.tag = new ClassesListTreeModel(abcPanel.classTree.treeList, filterField.getText()); } View.execInEventDispatch(new Runnable() { @Override public void run() { tagTree.updateUI(); } }); } } private static void getApplicationMenuButtons(Component comp, List ret) { if (comp instanceof JRibbonApplicationMenuButton) { ret.add((JRibbonApplicationMenuButton) comp); return; } if (comp instanceof java.awt.Container) { java.awt.Container cont = (java.awt.Container) comp; for (int i = 0; i < cont.getComponentCount(); i++) { getApplicationMenuButtons(cont.getComponent(i), ret); } } } @Override public void setVisible(boolean b) { super.setVisible(b); if (b) { if (abcPanel != null) { abcPanel.initSplits(); } if (actionPanel != null) { actionPanel.initSplits(); } final MainFrame t = this; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { List mbuttons = new ArrayList<>(); getApplicationMenuButtons(t, mbuttons); for (final JRibbonApplicationMenuButton mbutton : mbuttons) { mbutton.setIcon(View.getResizableIcon("buttonicon_256")); mbutton.setDisplayState(new CommandButtonDisplayState( "My Ribbon Application Menu Button", mbutton.getSize().width) { @Override public org.pushingpixels.flamingo.api.common.CommandButtonLayoutManager createLayoutManager( org.pushingpixels.flamingo.api.common.AbstractCommandButton commandButton) { return new CommandButtonLayoutManager() { @Override public int getPreferredIconSize() { return mbutton.getSize().width; } @Override public CommandButtonLayoutManager.CommandButtonLayoutInfo getLayoutInfo( AbstractCommandButton commandButton, Graphics g) { CommandButtonLayoutManager.CommandButtonLayoutInfo result = new CommandButtonLayoutManager.CommandButtonLayoutInfo(); result.actionClickArea = new Rectangle(0, 0, 0, 0); result.popupClickArea = new Rectangle(0, 0, commandButton .getWidth(), commandButton.getHeight()); result.popupActionRect = new Rectangle(0, 0, 0, 0); ResizableIcon icon = commandButton.getIcon(); icon.setDimension(new Dimension(commandButton.getWidth(), commandButton.getHeight())); result.iconRect = new Rectangle( 0, 0, commandButton.getWidth(), commandButton.getHeight()); result.isTextInActionArea = false; return result; } @Override public Dimension getPreferredSize( AbstractCommandButton commandButton) { return new Dimension(40, 40); } @Override public void propertyChange(PropertyChangeEvent evt) { } @Override public Point getKeyTipAnchorCenterPoint( AbstractCommandButton commandButton) { // dead center return new Point(commandButton.getWidth() / 2, commandButton.getHeight() / 2); } }; } }); MyRibbonApplicationMenuButtonUI mui = (MyRibbonApplicationMenuButtonUI) mbutton.getUI(); mui.setHoverIcon(View.getResizableIcon("buttonicon_hover_256")); mui.setNormalIcon(View.getResizableIcon("buttonicon_256")); mui.setClickIcon(View.getResizableIcon("buttonicon_down_256")); } splitPane1.setDividerLocation(Configuration.guiSplitPane1DividerLocation.get(getWidth() / 3)); int confDivLoc = Configuration.guiSplitPane2DividerLocation.get(splitPane2.getHeight() * 3 / 5); if (confDivLoc > splitPane2.getHeight() - 10) { //In older releases, divider location was saved when detailPanel was invisible too confDivLoc = splitPane2.getHeight() * 3 / 5; } splitPane2.setDividerLocation(confDivLoc); splitPos = splitPane2.getDividerLocation(); splitsInited = true; if (miGotoMainClassOnStartup.isSelected()) { gotoDocumentClass(); } } }); } } private void parseCharacters(List list) { for (ContainerItem t : list) { if (t instanceof CharacterTag) { characters.put(((CharacterTag) t).getCharacterId(), (CharacterTag) t); } if (t instanceof Container) { parseCharacters(((Container) t).getSubItems()); } } } public static void getShapes(List list, List shapes) { for (ContainerItem t : list) { if (t instanceof Container) { getShapes(((Container) t).getSubItems(), shapes); } if ((t instanceof DefineShapeTag) || (t instanceof DefineShape2Tag) || (t instanceof DefineShape3Tag) || (t instanceof DefineShape4Tag)) { shapes.add((Tag) t); } } } public static void getFonts(List list, List fonts) { for (ContainerItem t : list) { if (t instanceof Container) { getFonts(((Container) t).getSubItems(), fonts); } if ((t instanceof DefineFontTag) || (t instanceof DefineFont2Tag) || (t instanceof DefineFont3Tag) || (t instanceof DefineFont4Tag)) { fonts.add((Tag) t); } } } public static void getActionScript3(List list, List actionScripts) { for (ContainerItem t : list) { if (t instanceof Container) { getActionScript3(((Container) t).getSubItems(), actionScripts); } if (t instanceof ABCContainerTag) { actionScripts.add((ABCContainerTag) t); } } } public static void getMorphShapes(List list, List morphShapes) { for (ContainerItem t : list) { if (t instanceof Container) { getMorphShapes(((Container) t).getSubItems(), morphShapes); } if ((t instanceof DefineMorphShapeTag) || (t instanceof DefineMorphShape2Tag)) { morphShapes.add((Tag) t); } } } public static void getImages(List list, List images) { for (ContainerItem t : list) { if (t instanceof Container) { getImages(((Container) t).getSubItems(), images); } if ((t instanceof DefineBitsTag) || (t instanceof DefineBitsJPEG2Tag) || (t instanceof DefineBitsJPEG3Tag) || (t instanceof DefineBitsJPEG4Tag) || (t instanceof DefineBitsLosslessTag) || (t instanceof DefineBitsLossless2Tag)) { images.add((Tag) t); } } } public static void getTexts(List list, List texts) { for (ContainerItem t : list) { if (t instanceof Container) { getTexts(((Container) t).getSubItems(), texts); } if ((t instanceof DefineTextTag) || (t instanceof DefineText2Tag) || (t instanceof DefineEditTextTag)) { texts.add((Tag) t); } } } public static void getSprites(List list, List sprites) { for (ContainerItem t : list) { if (t instanceof Container) { getSprites(((Container) t).getSubItems(), sprites); } if (t instanceof DefineSpriteTag) { sprites.add((Tag) t); } } } public static void getButtons(List list, List buttons) { for (ContainerItem t : list) { if (t instanceof Container) { getButtons(((Container) t).getSubItems(), buttons); } if ((t instanceof DefineButtonTag) || (t instanceof DefineButton2Tag)) { buttons.add((Tag) t); } } } public List getSelectedNodes() { List 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 String getTagType(Object t) { if ((t instanceof DefineFontTag) || (t instanceof DefineFont2Tag) || (t instanceof DefineFont3Tag) || (t instanceof DefineFont4Tag) || (t instanceof DefineCompactedFont)) { return "font"; } if ((t instanceof DefineTextTag) || (t instanceof DefineText2Tag) || (t instanceof DefineEditTextTag)) { return "text"; } if ((t instanceof DefineBitsTag) || (t instanceof DefineBitsJPEG2Tag) || (t instanceof DefineBitsJPEG3Tag) || (t instanceof DefineBitsJPEG4Tag) || (t instanceof DefineBitsLosslessTag) || (t instanceof DefineBitsLossless2Tag)) { return "image"; } if ((t instanceof DefineShapeTag) || (t instanceof DefineShape2Tag) || (t instanceof DefineShape3Tag) || (t instanceof DefineShape4Tag)) { return "shape"; } if ((t instanceof DefineMorphShapeTag) || (t instanceof DefineMorphShape2Tag)) { return "morphshape"; } if (t instanceof DefineSpriteTag) { return "sprite"; } if ((t instanceof DefineButtonTag) || (t instanceof DefineButton2Tag)) { return "button"; } if (t instanceof ASMSource) { return "as"; } if (t instanceof TreeElement) { TreeElement te = (TreeElement) t; if (te.getItem() instanceof ScriptPack) { return "as"; } else { return "package"; } } if (t instanceof PackageNode) { return "package"; } if (t instanceof FrameNode) { return "frame"; } if (t instanceof ShowFrameTag) { return "showframe"; } if (t instanceof DefineVideoStreamTag) { return "movie"; } if ((t instanceof DefineSoundTag) || (t instanceof SoundStreamHeadTag) || (t instanceof SoundStreamHead2Tag)) { return "sound"; } if (t instanceof DefineBinaryDataTag) { return "binaryData"; } return "folder"; } public List getTagsWithType(List list, String type) { List ret = new ArrayList<>(); for (Object o : list) { String ttype = getTagType(o); if (type.equals(ttype)) { ret.add(o); } } return ret; } public List getTagNodesWithType(List list, String type, Object parent, boolean display) { List ret = new ArrayList<>(); int frameCnt = 0; for (ContainerItem o : list) { String ttype = getTagType(o); if ("showframe".equals(ttype) && "frame".equals(type)) { frameCnt++; ret.add(new TagNode(new FrameNode(frameCnt, parent, display))); } else if (type.equals(ttype)) { ret.add(new TagNode(o)); } } return ret; } public void renameIdentifier(String identifier) throws InterruptedException { String oldName = identifier; String newName = View.showInputDialog(translate("rename.enternew"), oldName); if (newName != null) { if (!oldName.equals(newName)) { swf.renameAS2Identifier(oldName, newName); View.showMessageDialog(null, translate("rename.finished.identifier")); doFilter(); reload(true); } } } public void renameMultiname(int multiNameIndex) { String oldName = ""; if (abcPanel.abc.constants.getMultiname(multiNameIndex).name_index > 0) { oldName = abcPanel.abc.constants.getString(abcPanel.abc.constants.getMultiname(multiNameIndex).name_index); } String newName = View.showInputDialog(translate("rename.enternew"), oldName); if (newName != null) { if (!oldName.equals(newName)) { int mulCount = 0; for (ABCContainerTag cnt : abcList) { ABC abc = cnt.getABC(); for (int m = 1; m < abc.constants.getMultinameCount(); m++) { int ni = abc.constants.getMultiname(m).name_index; String n = ""; if (ni > 0) { n = abc.constants.getString(ni); } if (n.equals(oldName)) { abc.renameMultiname(m, newName); mulCount++; } } } View.showMessageDialog(null, translate("rename.finished.multiname").replace("%count%", "" + mulCount)); if (abcPanel != null) { abcPanel.reload(); } doFilter(); reload(true); abcPanel.hilightScript(abcPanel.decompiledTextArea.getScriptLeaf().getPath().toString()); } } } public List getSelected(JTree tree) { TreeSelectionModel tsm = tree.getSelectionModel(); TreePath[] tps = tsm.getSelectionPaths(); List ret = new ArrayList<>(); if (tps == null) { return ret; } for (TreePath tp : tps) { Object o = tp.getLastPathComponent(); ret.add(o); } return ret; } public List getAllSubs(JTree tree, Object o) { TreeModel tm = tree.getModel(); List ret = new ArrayList<>(); for (int i = 0; i < tm.getChildCount(o); i++) { Object c = tm.getChild(o, i); ret.add(c); ret.addAll(getAllSubs(tree, c)); } return ret; } public List getAllSelected(JTree tree) { TreeSelectionModel tsm = tree.getSelectionModel(); TreePath[] tps = tsm.getSelectionPaths(); List ret = new ArrayList<>(); if (tps == null) { return ret; } for (TreePath tp : tps) { Object o = tp.getLastPathComponent(); ret.add(o); ret.addAll(getAllSubs(tree, o)); } return ret; } public TagNode getASTagNode(JTree tree) { TreeModel tm = tree.getModel(); if (tm == null) { return null; } Object root = tm.getRoot(); for (int i = 0; i < tm.getChildCount(root); i++) { Object node = tm.getChild(root, i); if (node instanceof TagNode) { Object tag = ((TagNode) tm.getChild(root, i)).tag; if (tag != null) { if ("scripts".equals(((TagNode) node).mark)) { return (TagNode) node; } } } } return null; } public List createTagList(List list, Object parent) { List ret = new ArrayList<>(); List frames = getTagNodesWithType(list, "frame", parent, true); List shapes = getTagNodesWithType(list, "shape", parent, true); List morphShapes = getTagNodesWithType(list, "morphshape", parent, true); List sprites = getTagNodesWithType(list, "sprite", parent, true); List buttons = getTagNodesWithType(list, "button", parent, true); List images = getTagNodesWithType(list, "image", parent, true); List fonts = getTagNodesWithType(list, "font", parent, true); List texts = getTagNodesWithType(list, "text", parent, true); List movies = getTagNodesWithType(list, "movie", parent, true); List sounds = getTagNodesWithType(list, "sound", parent, true); List binaryData = getTagNodesWithType(list, "binaryData", parent, true); List actionScript = new ArrayList<>(); for (int i = 0; i < sounds.size(); i++) { if (sounds.get(i).tag instanceof SoundStreamHeadTypeTag) { List blocks = new ArrayList<>(); SWF.populateSoundStreamBlocks(list, (Tag) sounds.get(i).tag, blocks); if (blocks.isEmpty()) { sounds.remove(i); i--; } } } for (TagNode n : sprites) { n.subItems = getTagNodesWithType(((DefineSpriteTag) n.tag).subTags, "frame", n.tag, true); } List exportAssetsTags = new ArrayList<>(); for (Object t : list) { if (t instanceof ExportAssetsTag) { exportAssetsTags.add((ExportAssetsTag) t); } /*if (t instanceof ASMSource) { TagNode tti = new TagNode(t); ret.add(tti); } else */ if (t instanceof Container) { TagNode tti = new TagNode(t); if (((Container) t).getItemCount() > 0) { List subItems = ((Container) t).getSubItems(); tti.subItems = createTagList(subItems, t); } //ret.add(tti); } } actionScript = SWF.createASTagList(list, null); TagNode textsNode = new TagNode(translate("node.texts")); textsNode.subItems.addAll(texts); TagNode imagesNode = new TagNode(translate("node.images")); imagesNode.subItems.addAll(images); TagNode moviesNode = new TagNode(translate("node.movies")); moviesNode.subItems.addAll(movies); TagNode soundsNode = new TagNode(translate("node.sounds")); soundsNode.subItems.addAll(sounds); TagNode binaryDataNode = new TagNode(translate("node.binaryData")); binaryDataNode.subItems.addAll(binaryData); TagNode fontsNode = new TagNode(translate("node.fonts")); fontsNode.subItems.addAll(fonts); TagNode spritesNode = new TagNode(translate("node.sprites")); spritesNode.subItems.addAll(sprites); TagNode shapesNode = new TagNode(translate("node.shapes")); shapesNode.subItems.addAll(shapes); TagNode morphShapesNode = new TagNode(translate("node.morphshapes")); morphShapesNode.subItems.addAll(morphShapes); TagNode buttonsNode = new TagNode(translate("node.buttons")); buttonsNode.subItems.addAll(buttons); TagNode framesNode = new TagNode(translate("node.frames")); framesNode.subItems.addAll(frames); TagNode actionScriptNode = new TagNode(translate("node.scripts")); actionScriptNode.mark = "scripts"; actionScriptNode.subItems.addAll(actionScript); if (!shapesNode.subItems.isEmpty()) { ret.add(shapesNode); } if (!morphShapesNode.subItems.isEmpty()) { ret.add(morphShapesNode); } if (!spritesNode.subItems.isEmpty()) { ret.add(spritesNode); } if (!textsNode.subItems.isEmpty()) { ret.add(textsNode); } if (!imagesNode.subItems.isEmpty()) { ret.add(imagesNode); } if (!moviesNode.subItems.isEmpty()) { ret.add(moviesNode); } if (!soundsNode.subItems.isEmpty()) { ret.add(soundsNode); } if (!buttonsNode.subItems.isEmpty()) { ret.add(buttonsNode); } if (!fontsNode.subItems.isEmpty()) { ret.add(fontsNode); } if (!binaryDataNode.subItems.isEmpty()) { ret.add(binaryDataNode); } if (!framesNode.subItems.isEmpty()) { ret.add(framesNode); } if (abcPanel != null) { actionScriptNode.subItems.clear(); actionScriptNode.tag = abcPanel.classTree.getModel(); } if ((!actionScriptNode.subItems.isEmpty()) || (abcPanel != null)) { ret.add(actionScriptNode); } return ret; } public boolean confirmExperimental() { return View.showConfirmDialog(null, translate("message.confirm.experimental"), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION; } private SearchDialog searchDialog; public List exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException { final ExportMode exportMode = ExportMode.get(export.getOption(ExportDialog.OPTION_ACTIONSCRIPT)); final boolean isMp3OrWav = export.getOption(ExportDialog.OPTION_SOUNDS) == 0; final boolean isFormatted = export.getOption(ExportDialog.OPTION_TEXTS) == 1; List ret = new ArrayList<>(); List sel = getAllSelected(tagTree); List tlsList = new ArrayList<>(); JPEGTablesTag jtt = null; for (Tag t : swf.tags) { if (t instanceof JPEGTablesTag) { jtt = (JPEGTablesTag) t; break; } } List images = new ArrayList<>(); List shapes = new ArrayList<>(); List movies = new ArrayList<>(); List sounds = new ArrayList<>(); List texts = new ArrayList<>(); List actionNodes = new ArrayList<>(); List binaryData = new ArrayList<>(); for (Object d : sel) { if (d instanceof TagNode) { TagNode n = (TagNode) d; if ("image".equals(getTagType(n.tag))) { images.add((Tag) n.tag); } if ("shape".equals(getTagType(n.tag))) { shapes.add((Tag) n.tag); } if ("as".equals(getTagType(n.tag))) { actionNodes.add(n); } if ("movie".equals(getTagType(n.tag))) { movies.add((Tag) n.tag); } if ("sound".equals(getTagType(n.tag))) { sounds.add((Tag) n.tag); } if ("binaryData".equals(getTagType(n.tag))) { binaryData.add((Tag) n.tag); } if ("text".equals(getTagType(n.tag))) { texts.add((Tag) n.tag); } } if (d instanceof TreeElement) { if (((TreeElement) d).isLeaf()) { tlsList.add((ScriptPack) ((TreeElement) d).getItem()); } } } ret.addAll(swf.exportImages(handler, selFile + File.separator + "images", images)); ret.addAll(SWF.exportShapes(handler, selFile + File.separator + "shapes", shapes)); ret.addAll(swf.exportTexts(handler, selFile + File.separator + "texts", texts, isFormatted)); ret.addAll(swf.exportMovies(handler, selFile + File.separator + "movies", movies)); ret.addAll(swf.exportSounds(handler, selFile + File.separator + "sounds", sounds, isMp3OrWav, isMp3OrWav)); ret.addAll(SWF.exportBinaryData(handler, selFile + File.separator + "binaryData", binaryData)); if (abcPanel != null) { for (int i = 0; i < tlsList.size(); i++) { ScriptPack tls = tlsList.get(i); Main.startWork(translate("work.exporting") + " " + (i + 1) + "/" + tlsList.size() + " " + tls.getPath() + " ..."); ret.add(tls.export(selFile, abcList, exportMode, Configuration.parallelSpeedUp.get())); } } else { List allNodes = new ArrayList<>(); TagNode asn = getASTagNode(tagTree); if (asn != null) { allNodes.add(asn); TagNode.setExport(allNodes, false); TagNode.setExport(actionNodes, true); ret.addAll(TagNode.exportNodeAS(swf.tags, handler, allNodes, selFile, exportMode, null)); } } return ret; } private void clearCache() { if (abcPanel != null) { abcPanel.decompiledTextArea.clearScriptCache(); } if (actionPanel != null) { actionPanel.clearCache(); } } public void gotoDocumentClass() { if (swf == null) { return; } String documentClass = null; loopdc: for (Tag t : swf.tags) { if (t instanceof SymbolClassTag) { SymbolClassTag sc = (SymbolClassTag) t; for (int i = 0; i < sc.tagIDs.length; i++) { if (sc.tagIDs[i] == 0) { documentClass = sc.classNames[i]; break loopdc; } } } } if (documentClass != null) { showDetail(DETAILCARDAS3NAVIGATOR); showCard(CARDACTIONSCRIPTPANEL); abcPanel.hilightScript(documentClass); } } private void fontAddChars(FontTag ft, Set selChars, String selFont) { FontTag f = (FontTag) oldValue; String oldchars = f.getCharacters(swf.tags); for (int ic : selChars) { char c = (char) ic; if (oldchars.indexOf((int) c) == -1) { Font font = new Font(selFont, f.getFontStyle(), 1024); if (!font.canDisplay(c)) { View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + c), translate("error"), JOptionPane.ERROR_MESSAGE); return; } } } String[] yesno = new String[]{translate("button.yes"), translate("button.no"), translate("button.yes.all"), translate("button.no.all")}; boolean yestoall = false; boolean notoall = false; for (int ic : selChars) { char c = (char) ic; if (oldchars.indexOf((int) c) > -1) { int opt; //yes if (!(yestoall || notoall)) { opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes")); if (opt == 2) { yestoall = true; } if (opt == 3) { notoall = true; } } if (yestoall) { opt = 0; //yes } else if (notoall) { opt = 1; //no } else { opt = 1; } if (opt == 1) { continue; } } f.addCharacter(swf.tags, c, fontSelection.getSelectedItem().toString()); oldchars += c; } } @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { case "FONTEMBED": if (oldValue instanceof FontTag) { FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), ((FontTag) oldValue).getFontStyle()); if (fed.display()) { Set selChars = fed.getSelectedChars(); if (!selChars.isEmpty()) { String selFont = fed.getSelectedFont(); fontSelection.setSelectedItem(selFont); fontAddChars((FontTag) oldValue, selChars, selFont); fontAddCharactersField.setText(""); reload(true); } } } break; case "SELECTCOLOR": Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectcolor.title"), View.swfBackgroundColor); if (newColor != null) { View.swfBackgroundColor = newColor; reload(true); } break; case "RELOAD": if (View.showConfirmDialog(null, translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { Main.reloadSWF(); } break; case "ADVANCEDSETTINGS": Main.advancedSettings(); break; case "LOADMEMORY": Main.loadFromMemory(); break; case "LOADCACHE": Main.loadFromCache(); break; case "SHOWERRORLOG": Main.displayErrorFrame(); break; case "FONTADDCHARS": String newchars = fontAddCharactersField.getText(); if (oldValue instanceof FontTag) { Set selChars = new TreeSet<>(); for (int c = 0; c < newchars.length(); c++) { selChars.add(newchars.codePointAt(c)); } fontAddChars((FontTag) oldValue, selChars, fontSelection.getSelectedItem().toString()); fontAddCharactersField.setText(""); reload(true); } break; case "GOTODOCUMENTCLASSONSTARTUP": Configuration.gotoMainClassOnStartup.set(miGotoMainClassOnStartup.isSelected()); break; case "CACHEONDISK": Configuration.cacheOnDisk.set(miCacheDisk.isSelected()); if (miCacheDisk.isSelected()) { Cache.setStorageType(Cache.STORAGE_FILES); } else { Cache.setStorageType(Cache.STORAGE_MEMORY); } break; case "SETLANGUAGE": new SelectLanguageDialog().display(); break; case "DISABLEDECOMPILATION": Configuration.decompile.set(!miDecompile.isSelected()); clearCache(); if (abcPanel != null) { abcPanel.reload(); } reload(true); doFilter(); break; case "ASSOCIATE": if (miAssociate.isSelected() == ContextMenuTools.isAddedToContextMenu()) { return; } ContextMenuTools.addToContextMenu(miAssociate.isSelected()); //Update checkbox menuitem accordingly (User can cancel rights elevation) new Timer().schedule(new TimerTask() { @Override public void run() { miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu()); } }, 1000); //It takes some time registry change to apply break; case "GOTODOCUMENTCLASS": gotoDocumentClass(); break; case "PARALLELSPEEDUP": String confStr = translate("message.confirm.parallel") + "\r\n"; if (miParallelSpeedUp.isSelected()) { confStr += " " + translate("message.confirm.on"); } else { confStr += " " + translate("message.confirm.off"); } if (View.showConfirmDialog(null, confStr, translate("message.parallel"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { Configuration.parallelSpeedUp.set((Boolean) miParallelSpeedUp.isSelected()); } else { miParallelSpeedUp.setSelected(!miParallelSpeedUp.isSelected()); } break; case "INTERNALVIEWERSWITCH": Configuration.internalFlashViewer.set(miInternalViewer.isSelected()); reload(true); break; case "SEARCHAS": if (searchDialog == null) { searchDialog = new SearchDialog(); } searchDialog.setVisible(true); if (searchDialog.result) { final String txt = searchDialog.searchField.getText(); if (!txt.isEmpty()) { if (abcPanel != null) { (new Thread() { @Override public void run() { if (abcPanel.search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) { View.execInEventDispatch(new Runnable() { @Override public void run() { showDetail(DETAILCARDAS3NAVIGATOR); showCard(CARDACTIONSCRIPTPANEL); } }); } else { View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); } } }).start(); } else { (new Thread() { @Override public void run() { if (actionPanel.search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) { View.execInEventDispatch(new Runnable() { @Override public void run() { showCard(CARDACTIONSCRIPTPANEL); } }); } else { View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); } } }).start(); } } } break; case "REPLACEIMAGE": Object tagObj = tagTree.getLastSelectedPathComponent(); if (tagObj == null) { return; } if (tagObj instanceof TagNode) { tagObj = ((TagNode) tagObj).tag; } if (tagObj instanceof ImageTag) { ImageTag it = (ImageTag) tagObj; if (it.importSupported()) { JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); fc.setFileFilter(new FileFilter() { @Override public boolean accept(File f) { return (f.getName().toLowerCase().endsWith(".jpg")) || (f.getName().toLowerCase().endsWith(".jpeg")) || (f.getName().toLowerCase().endsWith(".gif")) || (f.getName().toLowerCase().endsWith(".png")) || (f.isDirectory()); } @Override public String getDescription() { return translate("filter.images"); } }); JFrame f = new JFrame(); View.setWindowIcon(f); int returnVal = fc.showOpenDialog(f); if (returnVal == JFileChooser.APPROVE_OPTION) { Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); File selfile = Helper.fixDialogFile(fc.getSelectedFile()); byte[] data = Helper.readFile(selfile.getAbsolutePath()); try { it.setImage(data); swf.clearImageCache(); } catch (IOException ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "Invalid image", ex); View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); } reload(true); } } } break; case "REMOVEITEM": List sel = getSelected(tagTree); List tagsToRemove = new ArrayList<>(); for (Object o : sel) { Object tag = o; if (o instanceof TagNode) { tag = ((TagNode) o).tag; } if (tag instanceof Tag) { tagsToRemove.add((Tag) tag); } } 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) { swf.removeTag(tag); showCard(CARDEMPTYPANEL); 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) { swf.removeTag(tag); } showCard(CARDEMPTYPANEL); refreshTree(); } } break; case "EDITTEXT": setEditText(true); break; case "CANCELTEXT": setEditText(false); break; case "SAVETEXT": if (oldValue instanceof TextTag) { try { if (((TextTag) oldValue).setFormattedText(new MissingCharacterHandler() { @Override public boolean handle(FontTag font, List tags, char character) { String fontName = sourceFontsMap.get(font.getFontId()); if (fontName == null) { fontName = font.getFontName(tags); } fontName = FontTag.findInstalledFontName(fontName); Font f = new Font(fontName, font.getFontStyle(), 18); if (!f.canDisplay(character)) { View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + character), translate("error"), JOptionPane.ERROR_MESSAGE); return false; } font.addCharacter(tags, character, fontName); return true; } }, swf.tags, textValue.getText(), fontSelection.getSelectedItem().toString())) { setEditText(false); } } catch (ParseException ex) { View.showMessageDialog(null, translate("error.text.invalid").replace("%text%", ex.text).replace("%line%", "" + ex.line), translate("error"), JOptionPane.ERROR_MESSAGE); } } break; case "AUTODEOBFUSCATE": if (View.showConfirmDialog(this, translate("message.confirm.autodeobfuscate") + "\r\n" + (miAutoDeobfuscation.isSelected() ? translate("message.confirm.on") : translate("message.confirm.off")), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { Configuration.autoDeobfuscate.set(miAutoDeobfuscation.isSelected()); clearCache(); if (abcPanel != null) { abcPanel.reload(); } reload(true); doFilter(); } else { miAutoDeobfuscation.setSelected(!miAutoDeobfuscation.isSelected()); } break; case "EXIT": setVisible(false); if (Main.proxyFrame != null) { if (Main.proxyFrame.isVisible()) { return; } } Main.exit(); break; } if (Main.isWorking()) { return; } switch (e.getActionCommand()) { case "RENAMEONEIDENTIFIER": if (swf.fileAttributes.actionScript3) { final int multiName = abcPanel.decompiledTextArea.getMultinameUnderCursor(); if (multiName > 0) { (new Thread() { @Override public void run() { Main.startWork(translate("work.renaming") + "..."); renameMultiname(multiName); Main.stopWork(); } }).start(); } else { View.showMessageDialog(null, translate("message.rename.notfound.multiname"), translate("message.rename.notfound.title"), JOptionPane.INFORMATION_MESSAGE); } } else { final String identifier = actionPanel.getStringUnderCursor(); if (identifier != null) { (new Thread() { @Override public void run() { Main.startWork(translate("work.renaming") + "..."); try { renameIdentifier(identifier); } catch (InterruptedException ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); } Main.stopWork(); } }).start(); } else { View.showMessageDialog(null, translate("message.rename.notfound.identifier"), translate("message.rename.notfound.title"), JOptionPane.INFORMATION_MESSAGE); } } break; case "ABOUT": Main.about(); break; case "SHOWPROXY": Main.showProxy(); break; case "SUBLIMITER": if (e.getSource() instanceof JCheckBoxMenuItem) { Main.setSubLimiter(((JCheckBoxMenuItem) e.getSource()).getState()); } break; case "SAVE": try { Main.saveFile(Main.file); } catch (IOException ex) { Logger.getLogger(com.jpexs.decompiler.flash.gui.abc.ABCPanel.class.getName()).log(Level.SEVERE, null, ex); View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE); } break; case "SAVEAS": if (Main.saveFileDialog()) { setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + Main.getFileTitle() : "")); saveCommandButton.setEnabled(!Main.readOnly); } break; case "OPEN": Main.openFileDialog(); break; case "EXPORTFLA": JFileChooser fc = new JFileChooser(); String selDir = Configuration.lastOpenDir.get(); fc.setCurrentDirectory(new File(selDir)); if (!selDir.endsWith(File.separator)) { selDir += File.separator; } String fileName = (new File(Main.file).getName()); fileName = fileName.substring(0, fileName.length() - 4) + ".fla"; fc.setSelectedFile(new File(selDir + fileName)); FileFilter fla = new FileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || (f.getName().toLowerCase().endsWith(".fla")); } @Override public String getDescription() { return translate("filter.fla"); } }; FileFilter xfl = new FileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || (f.getName().toLowerCase().endsWith(".xfl")); } @Override public String getDescription() { return translate("filter.xfl"); } }; fc.setFileFilter(fla); fc.addChoosableFileFilter(xfl); fc.setAcceptAllFileFilterUsed(false); JFrame f = new JFrame(); View.setWindowIcon(f); int returnVal = fc.showSaveDialog(f); if (returnVal == JFileChooser.APPROVE_OPTION) { Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); File sf = Helper.fixDialogFile(fc.getSelectedFile()); Main.startWork(translate("work.exporting.fla") + "..."); final boolean compressed = fc.getFileFilter() == fla; if (!compressed) { if (sf.getName().endsWith(".fla")) { sf = new File(sf.getAbsolutePath().substring(0, sf.getAbsolutePath().length() - 4) + ".xfl"); } } final File selfile = sf; (new Thread() { @Override public void run() { Helper.freeMem(); try { if (compressed) { swf.exportFla(errorHandler, selfile.getAbsolutePath(), new File(Main.file).getName(), ApplicationInfo.applicationName, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get()); } else { swf.exportXfl(errorHandler, selfile.getAbsolutePath(), new File(Main.file).getName(), ApplicationInfo.applicationName, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get()); } } catch (IOException ex) { View.showMessageDialog(null, translate("error.export") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage(), translate("error"), JOptionPane.ERROR_MESSAGE); } Helper.freeMem(); Main.stopWork(); } }).start(); } break; case "EXPORTSEL": case "EXPORT": final ExportDialog export = new ExportDialog(); export.setVisible(true); if (!export.cancelled) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); chooser.setDialogTitle(translate("export.select.directory")); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setAcceptAllFileFilterUsed(false); if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { final long timeBefore = System.currentTimeMillis(); Main.startWork(translate("work.exporting") + "..."); final String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); Configuration.lastExportDir.set(Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath()); final ExportMode exportMode = ExportMode.get(export.getOption(ExportDialog.OPTION_ACTIONSCRIPT)); final boolean isMp3OrWav = export.getOption(ExportDialog.OPTION_SOUNDS) == 0; final boolean isFormatted = export.getOption(ExportDialog.OPTION_TEXTS) == 1; final boolean onlySel = e.getActionCommand().endsWith("SEL"); (new Thread() { @Override public void run() { try { if (onlySel) { exportSelection(errorHandler, selFile, export); } else { swf.exportImages(errorHandler, selFile + File.separator + "images"); swf.exportShapes(errorHandler, selFile + File.separator + "shapes"); swf.exportTexts(errorHandler, selFile + File.separator + "texts", isFormatted); swf.exportMovies(errorHandler, selFile + File.separator + "movies"); swf.exportSounds(errorHandler, selFile + File.separator + "sounds", isMp3OrWav, isMp3OrWav); swf.exportBinaryData(errorHandler, selFile + File.separator + "binaryData"); swf.exportActionScript(errorHandler, selFile, exportMode, Configuration.parallelSpeedUp.get()); } } catch (Exception ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "Error during export", ex); View.showMessageDialog(null, translate("error.export") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage()); } Main.stopWork(); long timeAfter = System.currentTimeMillis(); long timeMs = timeAfter - timeBefore; setStatus(translate("export.finishedin").replace("%time%", Helper.formatTimeSec(timeMs))); } }).start(); } } break; case "CHECKUPDATES": if (!Main.checkForUpdates()) { View.showMessageDialog(null, translate("update.check.nonewversion"), translate("update.check.title"), JOptionPane.INFORMATION_MESSAGE); } break; case "HELPUS": String helpUsURL = ApplicationInfo.projectPage + "/help_us.html"; if (java.awt.Desktop.isDesktopSupported()) { java.awt.Desktop desktop = java.awt.Desktop.getDesktop(); try { java.net.URI uri = new java.net.URI(helpUsURL); desktop.browse(uri); } catch (URISyntaxException | IOException ex) { } } else { View.showMessageDialog(null, translate("message.helpus").replace("%url%", helpUsURL)); } break; case "HOMEPAGE": String homePageURL = ApplicationInfo.projectPage; if (java.awt.Desktop.isDesktopSupported()) { java.awt.Desktop desktop = java.awt.Desktop.getDesktop(); try { java.net.URI uri = new java.net.URI(homePageURL); desktop.browse(uri); } catch (URISyntaxException | IOException ex) { } } else { View.showMessageDialog(null, translate("message.homepage").replace("%url%", homePageURL)); } break; case "RESTORECONTROLFLOW": case "RESTORECONTROLFLOWALL": Main.startWork(translate("work.restoringControlFlow")); final boolean all = e.getActionCommand().endsWith("ALL"); if ((!all) || confirmExperimental()) { new SwingWorker() { @Override protected Object doInBackground() throws Exception { int cnt = 0; if (all) { for (ABCContainerTag tag : abcPanel.list) { tag.getABC().restoreControlFlow(); } } else { int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex(); if (bi != -1) { abcPanel.abc.bodies[bi].restoreControlFlow(abcPanel.abc.constants, abcPanel.decompiledTextArea.getCurrentTrait(), abcPanel.abc.method_info[abcPanel.abc.bodies[bi].method_info]); } abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc, abcPanel.decompiledTextArea.getCurrentTrait()); } Main.stopWork(); View.showMessageDialog(null, "Control flow restored"); abcPanel.reload(); doFilter(); return true; } }.execute(); } break; case "RENAMEIDENTIFIERS": if (confirmExperimental()) { final RenameType renameType = new RenameDialog().display(); if (renameType != null) { Main.startWork(translate("work.renaming.identifiers") + "..."); new SwingWorker() { @Override protected Object doInBackground() throws Exception { try { int cnt = swf.deobfuscateIdentifiers(renameType); Main.stopWork(); View.showMessageDialog(null, translate("message.rename.renamed").replace("%count%", "" + cnt)); swf.assignClassesToSymbols(); clearCache(); if (abcPanel != null) { abcPanel.reload(); } doFilter(); reload(true); } catch (Exception ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "Error during renaming identifiers", ex); Main.stopWork(); View.showMessageDialog(null, translate("error.occured").replace("%error%", ex.getClass().getSimpleName())); } return true; } }.execute(); } } break; case "DEOBFUSCATE": case "DEOBFUSCATEALL": if (deobfuscationDialog == null) { deobfuscationDialog = new DeobfuscationDialog(); } deobfuscationDialog.setVisible(true); if (deobfuscationDialog.ok) { Main.startWork(translate("work.deobfuscating") + "..."); new SwingWorker() { @Override protected Object doInBackground() throws Exception { try { if (deobfuscationDialog.processAllCheckbox.isSelected()) { for (ABCContainerTag tag : abcPanel.list) { if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) { tag.getABC().removeDeadCode(); } else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) { tag.getABC().removeTraps(); } else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) { tag.getABC().removeTraps(); tag.getABC().restoreControlFlow(); } } } else { int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex(); Trait t = abcPanel.decompiledTextArea.getCurrentTrait(); if (bi != -1) { if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) { abcPanel.abc.bodies[bi].removeDeadCode(abcPanel.abc.constants, t, abcPanel.abc.method_info[abcPanel.abc.bodies[bi].method_info]); } else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) { abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, t, abcPanel.decompiledTextArea.getScriptLeaf().scriptIndex, abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic(), ""/*FIXME*/); } else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) { abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, t, abcPanel.decompiledTextArea.getScriptLeaf().scriptIndex, abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic(), ""/*FIXME*/); abcPanel.abc.bodies[bi].restoreControlFlow(abcPanel.abc.constants, t, abcPanel.abc.method_info[abcPanel.abc.bodies[bi].method_info]); } } abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc, t); } } catch (Exception ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "Deobfuscation error", ex); } Main.stopWork(); View.showMessageDialog(null, translate("work.deobfuscating.complete")); clearCache(); abcPanel.reload(); doFilter(); return true; } }.execute(); } break; case "REMOVENONSCRIPTS": List tags = new ArrayList<>(swf.tags); for (Tag tag : tags) { System.out.println(tag.getClass()); if (!(tag instanceof ABCContainerTag || tag instanceof ASMSource)) { swf.removeTag(tag); } } showCard(CARDEMPTYPANEL); refreshTree(); break; case "REFRESHDECOMPILED": clearCache(); if (abcPanel != null) { abcPanel.reload(); } reload(true); doFilter(); break; } } private int splitPos = 0; public void showDetailWithPreview(String card) { CardLayout cl = (CardLayout) (displayWithPreview.getLayout()); cl.show(displayWithPreview, card); } public void showDetail(String card) { CardLayout cl = (CardLayout) (detailPanel.getLayout()); cl.show(detailPanel, card); if (card.equals(DETAILCARDEMPTYPANEL)) { if (detailPanel.isVisible()) { splitPos = splitPane2.getDividerLocation(); detailPanel.setVisible(false); } } else { if (!detailPanel.isVisible()) { detailPanel.setVisible(true); splitPane2.setDividerLocation(splitPos); } } } public void showCard(String card) { CardLayout cl = (CardLayout) (displayPanel.getLayout()); cl.show(displayPanel, card); } private Object oldValue; private File tempFile; @Override public void valueChanged(TreeSelectionEvent e) { setEditText(false); reload(false); } private void stopFlashPlayer() { if (flashPanel != null) { if (!flashPanel.isStopped()) { flashPanel.stopSWF(); } } } private static Tag classicTag(Tag t) { if (t instanceof DefineCompactedFont) { return ((DefineCompactedFont) t).toClassicFont(); } return t; } public void reload(boolean forceReload) { Object tagObj = tagTree.getLastSelectedPathComponent(); if (tagObj == null) { return; } if (tagObj instanceof TagNode) { tagObj = ((TagNode) tagObj).tag; } if (tagObj instanceof TreeElement) { tagObj = ((TreeElement) tagObj).getItem(); } if (!forceReload && (tagObj == oldValue)) { return; } if (flashPanel != null) { flashPanel.specialPlayback = false; } swfPreviewPanel.stop(); stopFlashPlayer(); oldValue = tagObj; if (tagObj instanceof ScriptPack) { final ScriptPack scriptLeaf = (ScriptPack) tagObj; if (!Main.isWorking()) { Main.startWork(translate("work.decompiling") + "...", new Runnable() { @Override public void run() { if (setSourceTask != null) { setSourceTask.cancel(true); } abcPanel.decompiledTextArea.setText("//" + AppStrings.translate("work.canceled")); } }); FutureTask task = Helper.callAsync(new Callable() { @Override public Void call() throws Exception { int classIndex = -1; for (Trait t : scriptLeaf.abc.script_info[scriptLeaf.scriptIndex].traits.traits) { if (t instanceof TraitClass) { classIndex = ((TraitClass) t).class_info; break; } } abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setCode(""); abcPanel.navigator.setABC(abcList, scriptLeaf.abc); abcPanel.navigator.setClassIndex(classIndex, scriptLeaf.scriptIndex); abcPanel.setAbc(scriptLeaf.abc); abcPanel.decompiledTextArea.setScript(scriptLeaf, abcList); abcPanel.decompiledTextArea.setClassIndex(classIndex); abcPanel.decompiledTextArea.setNoTrait(); return null; } }, new Callback>() { @Override public void call(AsyncResult result) { setSourceTask = null; if (result.error != null) { abcPanel.decompiledTextArea.setText("//Decompilation error: " + result.error); } Main.stopWork(); } }); setSourceTask = task; } showDetail(DETAILCARDAS3NAVIGATOR); showCard(CARDACTIONSCRIPTPANEL); return; } else { showDetail(DETAILCARDEMPTYPANEL); } if ((tagObj instanceof SWFRoot)) { if (miInternalViewer.isSelected()) { showCard(CARDSWFPREVIEWPANEL); swfPreviewPanel.load(swf); swfPreviewPanel.play(); } else { showCard(CARDFLASHPANEL); parametersPanel.setVisible(false); if (flashPanel != null) { Color backgroundColor = View.DEFAULT_BACKGROUND_COLOR; for (Tag t : swf.tags) { if (t instanceof SetBackgroundColorTag) { backgroundColor = ((SetBackgroundColorTag) t).backgroundColor.toColor(); break; } } ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); if (tempFile != null) { tempFile.delete(); } try { tempFile = File.createTempFile("temp", ".swf"); tempFile.deleteOnExit(); swf.saveTo(new FileOutputStream(tempFile)); flashPanel.displaySWF(tempFile.getAbsolutePath(), backgroundColor, swf.frameRate); } catch (IOException iex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "Cannot create tempfile", iex); } } } } /*else if (tagObj instanceof DefineVideoStreamTag) { showCard(CARDEMPTYPANEL); } else if ((tagObj instanceof DefineSoundTag) || (tagObj instanceof SoundStreamHeadTag) || (tagObj instanceof SoundStreamHead2Tag)) { showCard(CARDEMPTYPANEL); } */ else if (tagObj instanceof DefineBinaryDataTag) { showCard(CARDEMPTYPANEL); } else if (tagObj instanceof ASMSource) { showCard(CARDACTIONSCRIPTPANEL); actionPanel.setSource((ASMSource) tagObj, !forceReload); } else if (tagObj instanceof ImageTag) { imageButtonsPanel.setVisible(((ImageTag) tagObj).importSupported()); showCard(CARDIMAGEPANEL); imagePanel.setImage(((ImageTag) tagObj).getImage(swf.tags)); } else if ((tagObj instanceof DrawableTag) && (!(tagObj instanceof TextTag)) && (!(tagObj instanceof FontTag)) && (miInternalViewer.isSelected())) { showCard(CARDDRAWPREVIEWPANEL); previewImagePanel.setDrawable((DrawableTag) tagObj, swf, characters, 50/*FIXME*/); } else if ((tagObj instanceof FontTag) && (miInternalViewer.isSelected())) { showCard(CARDFLASHPANEL); previewImagePanel.setDrawable((DrawableTag) tagObj, swf, characters, 50/*FIXME*/); showFontTag((FontTag) tagObj); } else if (tagObj instanceof FrameNode && ((FrameNode) tagObj).isDisplayed() && (miInternalViewer.isSelected())) { showCard(CARDDRAWPREVIEWPANEL); FrameNode fn = (FrameNode) tagObj; List controlTags = swf.tags; int containerId = 0; RECT rect = swf.displayRect; int totalFrameCount = swf.frameCount; if (fn.getParent() instanceof DefineSpriteTag) { controlTags = ((DefineSpriteTag) fn.getParent()).subTags; containerId = ((DefineSpriteTag) fn.getParent()).spriteId; rect = ((DefineSpriteTag) fn.getParent()).getRect(characters, new Stack()); totalFrameCount = ((DefineSpriteTag) fn.getParent()).frameCount; } previewImagePanel.setImage(SWF.frameToImage(containerId, ((FrameNode) tagObj).getFrame() - 1, swf.tags, controlTags, rect, totalFrameCount, new Stack())); } else if (((tagObj instanceof FrameNode) && ((FrameNode) tagObj).isDisplayed()) || ((tagObj instanceof CharacterTag) || (tagObj instanceof FontTag)) && (tagObj instanceof Tag)) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); try { if (tempFile != null) { tempFile.delete(); } tempFile = File.createTempFile("temp", ".swf"); tempFile.deleteOnExit(); Color backgroundColor = View.swfBackgroundColor; if (tagObj instanceof FontTag) { //Fonts are always black on white backgroundColor = View.DEFAULT_BACKGROUND_COLOR; } int frameCount = 1; int frameRate = swf.frameRate; HashMap videoFrames = new HashMap<>(); DefineVideoStreamTag vs = null; if (tagObj instanceof DefineVideoStreamTag) { vs = (DefineVideoStreamTag) tagObj; swf.populateVideoFrames(vs.getCharacterId(), swf.tags, videoFrames); frameCount = videoFrames.size(); } List soundFrames = new ArrayList<>(); if (tagObj instanceof SoundStreamHeadTypeTag) { SWF.populateSoundStreamBlocks(swf.tags, (Tag) tagObj, soundFrames); frameCount = soundFrames.size(); } if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) { frameCount = 100; frameRate = 50; } if (tagObj instanceof DefineSoundTag) { frameCount = 1; } try (FileOutputStream fos = new FileOutputStream(tempFile)) { SWFOutputStream sos = new SWFOutputStream(fos, 10); sos.write("FWS".getBytes()); sos.write(swf.version); ByteArrayOutputStream baos = new ByteArrayOutputStream(); SWFOutputStream sos2 = new SWFOutputStream(baos, 10); int width = swf.displayRect.Xmax - swf.displayRect.Xmin; int height = swf.displayRect.Ymax - swf.displayRect.Ymin; sos2.writeRECT(swf.displayRect); sos2.writeUI8(0); sos2.writeUI8(frameRate); sos2.writeUI16(frameCount); //framecnt /*FileAttributesTag fa = new FileAttributesTag(); sos2.writeTag(fa); */ if (tagObj instanceof FrameNode) { FrameNode fn = (FrameNode) tagObj; if (fn.getParent() == null) { for (Tag t : swf.tags) { if (t instanceof SetBackgroundColorTag) { backgroundColor = ((SetBackgroundColorTag) t).backgroundColor.toColor(); break; } } } } sos2.writeTag(new SetBackgroundColorTag(null, new RGB(backgroundColor))); if (tagObj instanceof FrameNode) { FrameNode fn = (FrameNode) tagObj; Object parent = fn.getParent(); List subs = new ArrayList<>(); if (parent == null) { subs.addAll(swf.tags); } else { if (parent instanceof Container) { subs = ((Container) parent).getSubItems(); } } List doneCharacters = new ArrayList<>(); int frameCnt = 1; for (Object o : subs) { if (o instanceof ShowFrameTag) { frameCnt++; continue; } if (frameCnt > fn.getFrame()) { break; } Tag t = (Tag) o; Set needed = t.getDeepNeededCharacters(characters, new ArrayList()); for (int n : needed) { if (!doneCharacters.contains(n)) { sos2.writeTag(classicTag(characters.get(n))); doneCharacters.add(n); } } if (t instanceof CharacterTag) { doneCharacters.add(((CharacterTag) t).getCharacterId()); } sos2.writeTag(classicTag(t)); if (parent != null) { if (t instanceof PlaceObjectTypeTag) { PlaceObjectTypeTag pot = (PlaceObjectTypeTag) t; int chid = pot.getCharacterId(); int depth = pot.getDepth(); MATRIX mat = pot.getMatrix(); if (mat == null) { mat = new MATRIX(); } mat = (MATRIX) Helper.deepCopy(mat); if (parent instanceof BoundedTag) { RECT r = ((BoundedTag) parent).getRect(characters, new Stack()); mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2; mat.translateY = mat.translateY + height / 2 - r.getHeight() / 2; } else { mat.translateX += width / 2; mat.translateY += height / 2; } sos2.writeTag(new PlaceObject2Tag(null, false, false, false, false, false, true, false, true, depth, chid, mat, null, 0, null, 0, null)); } } } sos2.writeTag(new ShowFrameTag(null)); } else { if (tagObj instanceof DefineBitsTag) { if (jtt != null) { sos2.writeTag(jtt); } } else if (tagObj instanceof AloneTag) { } else { Set needed = ((Tag) tagObj).getDeepNeededCharacters(characters, new ArrayList()); for (int n : needed) { sos2.writeTag(classicTag(characters.get(n))); } } sos2.writeTag(classicTag((Tag) tagObj)); int chtId = 0; if (tagObj instanceof CharacterTag) { chtId = ((CharacterTag) tagObj).getCharacterId(); } MATRIX mat = new MATRIX(); mat.hasRotate = false; mat.hasScale = false; mat.translateX = 0; mat.translateY = 0; if (tagObj instanceof BoundedTag) { RECT r = ((BoundedTag) tagObj).getRect(characters, new Stack()); mat.translateX = -r.Xmin; mat.translateY = -r.Ymin; mat.translateX = mat.translateX + width / 2 - r.getWidth() / 2; mat.translateY = mat.translateY + height / 2 - r.getHeight() / 2; } else { mat.translateX = width / 4; mat.translateY = height / 4; } if (tagObj instanceof FontTag) { int countGlyphs = ((FontTag) tagObj).getGlyphShapeTable().size(); int fontId = ((FontTag) tagObj).getFontId(); int sloupcu = (int) Math.ceil(Math.sqrt(countGlyphs)); int radku = (int) Math.ceil(((float) countGlyphs) / ((float) sloupcu)); int x = 0; int y = 1; for (int f = 0; f < countGlyphs; f++) { if (x >= sloupcu) { x = 0; y++; } List rec = new ArrayList<>(); TEXTRECORD tr = new TEXTRECORD(); int textHeight = height / radku; tr.fontId = fontId; tr.styleFlagsHasFont = true; tr.textHeight = textHeight; tr.glyphEntries = new GLYPHENTRY[1]; tr.styleFlagsHasColor = true; tr.textColor = new RGB(0, 0, 0); tr.glyphEntries[0] = new GLYPHENTRY(); tr.glyphEntries[0].glyphAdvance = 0; tr.glyphEntries[0].glyphIndex = f; rec.add(tr); mat.translateX = x * width / sloupcu; mat.translateY = y * height / radku; sos2.writeTag(new DefineTextTag(null, 999 + f, new RECT(0, width, 0, height), new MATRIX(), rec)); sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, true, false, 1 + f, 999 + f, mat, null, 0, null, 0, null)); x++; } sos2.writeTag(new ShowFrameTag(null)); } else if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) { sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null)); sos2.writeTag(new ShowFrameTag(null)); int numFrames = 100; for (int ratio = 0; ratio < 65536; ratio += 65536 / numFrames) { sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, false, true, 1, chtId, mat, null, ratio, null, 0, null)); sos2.writeTag(new ShowFrameTag(null)); } } else if (tagObj instanceof SoundStreamHeadTypeTag) { for (SoundStreamBlockTag blk : soundFrames) { sos2.writeTag(blk); sos2.writeTag(new ShowFrameTag(null)); } } else if (tagObj instanceof DefineSoundTag) { ExportAssetsTag ea = new ExportAssetsTag(); DefineSoundTag ds = (DefineSoundTag) tagObj; ea.tags.add(ds.soundId); ea.names.add("my_define_sound"); sos2.writeTag(ea); List actions; DoActionTag doa; doa = new DoActionTag(null, new byte[]{}, SWF.DEFAULT_VERSION, 0); actions = ASMParser.parse(0, 0, false, "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n" + "Push \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\" 0.0 \"Sound\"\n" + "NewObject\n" + "SetMember\n" + "Push \"my_define_sound\" 1 \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\"\n" + "GetMember\n" + "Push \"attachSound\"\n" + "CallMethod\n" + "Pop\n" + "Stop", SWF.DEFAULT_VERSION, false); doa.setActions(actions, SWF.DEFAULT_VERSION); sos2.writeTag(doa); sos2.writeTag(new ShowFrameTag(null)); actions = ASMParser.parse(0, 0, false, "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"start\"\n" + "StopSounds\n" + "Push \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\" 0.0 \"Sound\"\n" + "NewObject\n" + "SetMember\n" + "Push \"my_define_sound\" 1 \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\"\n" + "GetMember\n" + "Push \"attachSound\"\n" + "CallMethod\n" + "Pop\n" + "Push 9999 0.0 2 \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\"\n" + "GetMember\n" + "Push \"start\"\n" + "CallMethod\n" + "Pop\n" + "Stop", SWF.DEFAULT_VERSION, false); doa.setActions(actions, SWF.DEFAULT_VERSION); sos2.writeTag(doa); sos2.writeTag(new ShowFrameTag(null)); actions = ASMParser.parse(0, 0, false, "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\" \"onSoundComplete\" \"start\" \"execParam\"\n" + "StopSounds\n" + "Push \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\" 0.0 \"Sound\"\n" + "NewObject\n" + "SetMember\n" + "Push \"my_define_sound\" 1 \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\"\n" + "GetMember\n" + "Push \"attachSound\"\n" + "CallMethod\n" + "Pop\n" + "Push \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\"\n" + "GetMember\n" + "Push \"onSoundComplete\"\n" + "DefineFunction2 \"\" 0 2 false true true false true false true false false {\n" + "Push 0.0 register1 \"my_sound\"\n" + "GetMember\n" + "Push \"start\"\n" + "CallMethod\n" + "Pop\n" + "}\n" + "SetMember\n" + "Push \"_root\"\n" + "GetVariable\n" + "Push \"execParam\"\n" + "GetMember\n" + "Push 1 \"_root\"\n" + "GetVariable\n" + "Push \"my_sound\"\n" + "GetMember\n" + "Push \"start\"\n" + "CallMethod\n" + "Pop\n" + "Stop", SWF.DEFAULT_VERSION, false); doa.setActions(actions, SWF.DEFAULT_VERSION); sos2.writeTag(doa); sos2.writeTag(new ShowFrameTag(null)); actions = ASMParser.parse(0, 0, false, "StopSounds\n" + "Stop", SWF.DEFAULT_VERSION, false); doa.setActions(actions, SWF.DEFAULT_VERSION); sos2.writeTag(doa); sos2.writeTag(new ShowFrameTag(null)); sos2.writeTag(new ShowFrameTag(null)); if (flashPanel != null) { flashPanel.specialPlayback = true; } } else if (tagObj instanceof DefineVideoStreamTag) { sos2.writeTag(new PlaceObject2Tag(null, false, false, false, false, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null)); List frs = new ArrayList<>(videoFrames.values()); Collections.sort(frs, new Comparator() { @Override public int compare(VideoFrameTag o1, VideoFrameTag o2) { return o1.frameNum - o2.frameNum; } }); boolean first = true; int ratio = 0; for (VideoFrameTag f : frs) { if (!first) { ratio++; sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, false, false, true, 1, 0, null, null, ratio, null, 0, null)); } sos2.writeTag(f); sos2.writeTag(new ShowFrameTag(null)); first = false; } } else { sos2.writeTag(new PlaceObject2Tag(null, false, false, false, true, false, true, true, false, 1, chtId, mat, null, 0, null, 0, null)); sos2.writeTag(new ShowFrameTag(null)); } }//not showframe sos2.writeTag(new EndTag(null)); byte[] data = baos.toByteArray(); sos.writeUI32(sos.getPos() + data.length + 4); sos.write(data); fos.flush(); } showCard(CARDFLASHPANEL); if (flashPanel != null) { flashPanel.displaySWF(tempFile.getAbsolutePath(), backgroundColor, frameRate); } } catch (IOException | com.jpexs.decompiler.flash.action.parser.ParseException ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex); } if (tagObj instanceof TextTag) { parametersPanel.setVisible(true); previewSplitPane.setDividerLocation(previewSplitPane.getWidth() / 2); showDetailWithPreview(CARDTEXTPANEL); textValue.setText(((TextTag) tagObj).getFormattedText(swf.tags)); } else if (tagObj instanceof FontTag) { showFontTag((FontTag) tagObj); } else { parametersPanel.setVisible(false); } } else { showCard(CARDEMPTYPANEL); } } private void showFontTag(FontTag ft) { if (miInternalViewer.isSelected() /*|| ft instanceof GFxDefineCompactedFont*/) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, INTERNAL_VIEWER_CARD); internelViewerPanel.setDrawable(ft, swf, characters, 1); } else { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); } parametersPanel.setVisible(true); previewSplitPane.setDividerLocation(previewSplitPane.getWidth() / 2); fontNameLabel.setText(ft.getFontName(swf.tags)); fontIsBoldLabel.setText(ft.isBold() ? translate("yes") : translate("no")); fontIsItalicLabel.setText(ft.isItalic() ? translate("yes") : translate("no")); fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : "" + ft.getDescent()); fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : "" + ft.getAscent()); fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading()); String chars = ft.getCharacters(swf.tags); fontCharactersTextArea.setText(chars); if (sourceFontsMap.containsKey(ft.getFontId())) { fontSelection.setSelectedItem(sourceFontsMap.get(ft.getFontId())); } else { fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName(swf.tags))); } fontChangeList.componentResized(null); showDetailWithPreview(CARDFONTPANEL); } public void refreshTree() { List objs = new ArrayList<>(); objs.addAll(swf.tags); List> expandedNodes = getExpandedNodes(tagTree); tagTree.setModel(new TagTreeModel(createTagList(objs, null), new SWFRoot((new File(Main.file)).getName()))); expandTreeNodes(tagTree, expandedNodes); } private List> getExpandedNodes(JTree tree) { List> expandedNodes = new ArrayList<>(); int rowCount = tree.getRowCount(); for (int i = 0; i < rowCount; i++) { TreePath path = tree.getPathForRow(i); if (tree.isExpanded(path)) { List pathAsStringList = new ArrayList<>(); for (Object pathCompnent : path.getPath()) { pathAsStringList.add(pathCompnent.toString()); } expandedNodes.add(pathAsStringList); } } return expandedNodes; } private void expandTreeNodes(JTree tree, List> pathsToExpand) { for (List pathAsStringList : pathsToExpand) { expandTreeNode(tree, pathAsStringList); } } private void expandTreeNode(JTree tree, List pathAsStringList) { TreeModel model = tree.getModel(); Object node = model.getRoot(); if (pathAsStringList.isEmpty()) { return; } if (!pathAsStringList.get(0).equals(node.toString())) { return; } List path = new ArrayList<>(); path.add(node); for (int i = 1; i < pathAsStringList.size(); i++) { String name = pathAsStringList.get(i); int childCount = model.getChildCount(node); for (int j = 0; j < childCount; j++) { Object child = model.getChild(node, j); if (child.toString().equals(name)) { node = child; path.add(node); break; } } } TreePath tp = new TreePath(path.toArray(new Object[path.size()])); tree.expandPath(tp); } public void setEditText(boolean edit) { textValue.setEditable(edit); textSaveButton.setVisible(edit); textEditButton.setVisible(!edit); textCancelButton.setVisible(edit); if (!edit) { reload(true); } } @Override public void free() { Helper.emptyObject(this); } public void clearErrorState() { errorNotificationButton.setIcon(View.getIcon("okay16")); errorNotificationButton.setToolTipText(translate("errors.none")); } private Timer blinkTimer; private int blinkPos; public void setErrorState() { if (errorNotificationButton == null) { // todo: honfika // why null? return; } errorNotificationButton.setIcon(View.getIcon("error16")); errorNotificationButton.setToolTipText(translate("errors.present")); if (blinkTimer != null) { blinkTimer.cancel(); } blinkTimer = new Timer(); blinkTimer.schedule(new TimerTask() { @Override public void run() { View.execInEventDispatch(new Runnable() { @Override public void run() { blinkPos++; if ((blinkPos % 2) == 0 || (blinkPos >= 4)) { errorNotificationButton.setIcon(View.getIcon("error16")); } else { errorNotificationButton.setIcon(null); errorNotificationButton.setSize(16, 16); } } }); if (blinkPos >= 4) { cancel(); } } }, 500, 500); } }