diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameClassic.java b/src/com/jpexs/decompiler/flash/gui/MainFrameClassic.java index d0b8cc33d..d4507e9d1 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameClassic.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameClassic.java @@ -50,6 +50,7 @@ public final class MainFrameClassic extends AppFrame implements MainFrame { boolean externalFlashPlayerUnavailable = flashPanel == null; mainMenu = new MainFrameClassicMenu(this, externalFlashPlayerUnavailable); + mainMenu.createMenuBar(); panel = new MainPanel(this, mainMenu, flashPanel); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java index 3122e78d5..52676f45a 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java @@ -16,22 +16,19 @@ */ package com.jpexs.decompiler.flash.gui; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.console.ContextMenuTools; -import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.sun.jna.Platform; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.List; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import javax.swing.ButtonGroup; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; -import javax.swing.JOptionPane; import javax.swing.JRadioButtonMenuItem; +import javax.swing.MenuElement; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; @@ -43,529 +40,307 @@ public class MainFrameClassicMenu extends MainFrameMenu { private final MainFrameClassic mainFrame; - private JCheckBoxMenuItem miAutoDeobfuscation; - - private JCheckBoxMenuItem miInternalViewer; - - private JCheckBoxMenuItem miParallelSpeedUp; - - private JCheckBoxMenuItem miAssociate; - - private JCheckBoxMenuItem miDecompile; - - private JCheckBoxMenuItem miCacheDisk; - - private JCheckBoxMenuItem miGotoMainClassOnStartup; - - private JCheckBoxMenuItem miAutoRenameIdentifiers; - private ButtonGroup viewGroup; - - private JRadioButtonMenuItem miViewResources; - private JRadioButtonMenuItem miViewHex; - - private JCheckBoxMenuItem miDebuggerSwitch; - private JMenuItem miDebuggerReplaceTrace; - - private JCheckBoxMenuItem miViewTimeline; - - private ButtonGroup grpDeobfuscation; - private JRadioButtonMenuItem miDeobfuscationModeOld; - private JRadioButtonMenuItem miDeobfuscationModeNew; - private JMenu menuRecent; - - private JMenuItem miReload; - private JMenuItem miExportAll; - private JMenuItem miExportXml; - private JMenuItem miExportSel; - private JMenuItem miExportFla; - private JMenuItem miSave; - private JMenuItem miSaveAs; - private JMenuItem miSaveAsExe; - private JMenuItem miClose; - private JMenuItem miCloseAll; - - private JMenu menuExport; - private JMenuItem miImportText; - private JMenuItem miImportScript; - private JMenuItem miImportSymbolClass; - private JMenuItem miImportXml; - private JMenu menuImport; - private JMenuItem miRenameIdentifiers; - private JMenuItem miRenameOneIdentifier; - - private JMenuItem miReplace; - private JMenuItem miSearch; - private JMenuItem miDeobfuscation; - private JMenuItem miGotoDocumentClass; - public MainFrameClassicMenu(MainFrameClassic mainFrame, boolean externalFlashPlayerUnavailable) { - super(mainFrame); + super(mainFrame, externalFlashPlayerUnavailable); this.mainFrame = mainFrame; - createMenuBar(externalFlashPlayerUnavailable); } - @Override - public boolean isInternalFlashViewerSelected() { - return miInternalViewer.isSelected(); - } + private final Map menuElements = new HashMap<>(); + private final Map> menuGroups = new HashMap<>(); + private final Map menuButtonGroups = new HashMap<>(); - private String fixCommandTitle(String title) { - if (title.length() > 2) { - if (title.charAt(1) == ' ') { - title = title.charAt(0) + "\u00A0" + title.substring(2); - } + private void addMenu(String path, String title, String icon, final ActionListener subLoader) { + path = mapping(path); + final String fpath = path; + if (path.equals("_") || path.startsWith("_/")) { + return; } - return title; - } + String parentPath = ""; + if (path.contains("/")) { + parentPath = path.substring(0, path.lastIndexOf("/")); + } + MenuElement parentMenu = menuElements.get(parentPath); + if (parentMenu == null) { + throw new IllegalArgumentException("Parent menu " + path + " does not exist"); + } + JMenu menu = new JMenu(title); + if (icon != null) { + menu.setIcon(View.getIcon(icon, 16)); + } + if (parentMenu instanceof JMenuBar) { + ((JMenuBar) parentMenu).add(menu); + } + if (parentMenu instanceof JMenu) { + ((JMenu) parentMenu).add(menu); + if (subLoader != null) { + ((JMenu) parentMenu).addMenuListener(new MenuListener() { - private void loadRecent() { - List recentFiles = Configuration.getRecentFiles(); - menuRecent.removeAll(); - for (int i = recentFiles.size() - 1; i >= 0; i--) { - JMenuItem miRecent = new JMenuItem(recentFiles.get(i)); - final String f = recentFiles.get(i); - miRecent.addActionListener((ActionEvent e) -> { - if (Main.openFile(f, null) == OpenFileResult.NOT_FOUND) { - if (View.showConfirmDialog(null, translate("message.confirm.recentFileNotFound"), translate("message.confirm"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_NO_OPTION) { - Configuration.removeRecentFile(f); + @Override + public void menuSelected(MenuEvent e) { + subLoader.actionPerformed(new ActionEvent(menu, 0, "load:" + fpath)); } - } - }); - menuRecent.add(miRecent); + + @Override + public void menuDeselected(MenuEvent e) { + } + + @Override + public void menuCanceled(MenuEvent e) { + } + }); + }; } + menuElements.put(path, menu); } - private void createMenuBar(boolean externalFlashPlayerUnavailable) { - JMenuBar menuBar = new JMenuBar(); + @Override + public void addMenuItem(String path, String title, String icon, ActionListener action, int priority, final ActionListener subLoader, boolean isLeaf) { + path = mapping(path); - JMenuItem miOpen = new JMenuItem(translate("menu.file.open")); - miOpen.setIcon(View.getIcon("open16")); - miOpen.addActionListener(this::open); - - menuRecent = new JMenu(translate("menu.recentFiles")); - - miSave = new JMenuItem(translate("menu.file.save")); - miSave.setIcon(View.getIcon("save16")); - miSave.addActionListener(this::save); - miSaveAs = new JMenuItem(translate("menu.file.saveas")); - miSaveAs.setIcon(View.getIcon("saveas16")); - miSaveAs.addActionListener(this::saveAs); - miSaveAsExe = new JMenuItem(translate("menu.file.saveasexe")); - miSaveAsExe.setIcon(View.getIcon("saveasexe16")); - miSaveAsExe.addActionListener(this::saveAsExe); - - miReload = new JMenuItem(translate("menu.file.reload")); - miReload.setIcon(View.getIcon("reload16")); - miReload.addActionListener(this::reload); - - miExportFla = new JMenuItem(translate("menu.file.export.fla")); - miExportFla.addActionListener(this::exportFla); - miExportFla.setIcon(View.getIcon("flash16")); - - miExportAll = new JMenuItem(translate("menu.file.export.all")); - miExportAll.addActionListener(this::exportAll); - miExportAll.setIcon(View.getIcon("export16")); - - miExportSel = new JMenuItem(translate("menu.file.export.selection")); - miExportSel.addActionListener(this::exportSelected); - miExportSel.setIcon(View.getIcon("exportsel16")); - - miExportXml = new JMenuItem(translate("menu.file.export.xml")); - miExportXml.addActionListener(this::exportSwfXml); - miExportXml.setIcon(View.getIcon("exportxml32", 16)); - - menuExport = new JMenu(translate("menu.export")); - menuExport.add(miExportFla); - menuExport.add(miExportXml); - menuExport.addSeparator(); - menuExport.add(miExportAll); - menuExport.add(miExportSel); - - miImportText = new JMenuItem(translate("menu.file.import.text")); - miImportText.addActionListener(this::importText); - miImportText.setIcon(View.getIcon("importtext32", 16)); - - miImportScript = new JMenuItem(translate("menu.file.import.script")); - miImportScript.addActionListener(this::importScript); - miImportScript.setIcon(View.getIcon("importtext32", 16)); - - miImportSymbolClass = new JMenuItem(translate("menu.file.import.symbolClass")); - miImportSymbolClass.addActionListener(this::importSymbolClass); - miImportSymbolClass.setIcon(View.getIcon("importsymbolclass32", 16)); - - miImportXml = new JMenuItem(translate("menu.file.import.xml")); - miImportXml.addActionListener(this::importSwfXml); - miImportXml.setIcon(View.getIcon("importxml32", 16)); - menuImport = new JMenu(translate("menu.import")); - menuImport.add(miImportXml); - menuImport.add(miImportText); - menuImport.add(miImportScript); - menuImport.add(miImportSymbolClass); - - /* - JMenuItem menuX; - menuX = new JMenuItem(translate("menu.file.export.all")); - menuX.addActionListener(this::exportAll); - menuX.setIcon(View.getIcon("export16")); - menu.file.close - */ - miClose = new JMenuItem(translate("menu.file.close")); - miClose.addActionListener(this::close); - miClose.setIcon(View.getIcon("close32", 16)); - - miCloseAll = new JMenuItem(translate("menu.file.closeAll")); - miCloseAll.addActionListener(this::closeAll); - miCloseAll.setIcon(View.getIcon("close32", 16)); - - JMenuItem miExit = new JMenuItem(translate("menu.file.exit")); - miExit.setIcon(View.getIcon("exit16")); - miExit.addActionListener(this::exit); - - JMenu menuFile = new JMenu(translate("menu.file")); - - menuFile.addMenuListener(new MenuListener() { - - @Override - public void menuSelected(MenuEvent e) { - loadRecent(); - } - - @Override - public void menuDeselected(MenuEvent e) { - - } - - @Override - public void menuCanceled(MenuEvent e) { - - } - }); - - menuFile.add(miOpen); - menuFile.add(menuRecent); - menuFile.add(miSave); - menuFile.add(miSaveAs); - menuFile.add(miSaveAsExe); - menuFile.add(miReload); - menuFile.addSeparator(); - - menuFile.add(menuExport); - menuFile.add(menuImport); - menuFile.addSeparator(); - - menuFile.add(miClose); - menuFile.add(miCloseAll); - menuFile.addSeparator(); - - menuFile.add(miExit); - - menuBar.add(menuFile); - - miViewResources = new JRadioButtonMenuItem(translate("menu.file.view.resources")); - miViewResources.addActionListener(this::viewModeResourcesButtonActionPerformed); - miViewResources.setIcon(View.getIcon("viewresources16")); - - miViewHex = new JRadioButtonMenuItem(translate("menu.file.view.hex")); - miViewHex.addActionListener(this::viewModeHexDumpButtonActionPerformed); - miViewHex.setIcon(View.getIcon("viewhex16")); - - viewGroup = new ButtonGroup(); - viewGroup.add(miViewResources); - viewGroup.add(miViewHex); - - if (Configuration.dumpView.get()) { - miViewHex.setSelected(true); + if (!isLeaf) { + //action is ignored + addMenu(path, title, icon, subLoader); + return; + } + if (path.startsWith("_/")) { + return; + } + String parentPath = ""; + if (path.contains("/")) { + parentPath = path.substring(0, path.lastIndexOf("/")); + } + MenuElement parentMenu = menuElements.get(parentPath); + if (parentMenu == null) { + throw new IllegalArgumentException("Parent menu " + path + " does not exist"); + } + JMenuItem menuItem = new JMenuItem(title); + if (icon != null) { + menuItem.setIcon(View.getIcon(icon, 16)); + } + if (action != null) { + menuItem.addActionListener(action); + } + if (parentMenu instanceof JMenu) { + ((JMenu) parentMenu).add(menuItem); } else { - miViewResources.setSelected(true); + throw new IllegalArgumentException("Parent path " + path + " is not a menu"); } + menuElements.put(path, menuItem); + } - JMenu menuView = new JMenu(translate("menu.view")); - menuView.add(miViewResources); - menuView.add(miViewHex); - - menuBar.add(menuView); - miDebuggerSwitch = new JCheckBoxMenuItem(translate("menu.debugger.switch")); - miDebuggerSwitch.addActionListener(this::debuggerSwitchButtonActionPerformed); - miDebuggerSwitch.setIcon(View.getIcon("debugger32", 16)); - - miDebuggerReplaceTrace = new JMenuItem(translate("menu.debugger.replacetrace")); - miDebuggerReplaceTrace.addActionListener(this::debuggerReplaceTraceCalls); - miDebuggerReplaceTrace.setIcon(View.getIcon("debuggerreplace16")); - - JMenuItem miDebuggerShowLog = new JMenuItem(translate("menu.debugger.showlog")); - miDebuggerShowLog.addActionListener(this::debuggerShowLog); - miDebuggerShowLog.setIcon(View.getIcon("debuggerlog16")); - - JMenu menuDebugger = new JMenu(translate("menu.debugger")); - menuDebugger.add(miDebuggerSwitch); - menuDebugger.add(miDebuggerReplaceTrace); - menuDebugger.add(miDebuggerShowLog); - - JMenu menuDeobfuscation = new JMenu(translate("menu.tools.deobfuscation")); - menuDeobfuscation.setIcon(View.getIcon("deobfuscate16")); - - miDeobfuscation = new JMenuItem(translate("menu.tools.deobfuscation.pcode")); - miDeobfuscation.addActionListener(this::deobfuscate); - - miAutoDeobfuscation = new JCheckBoxMenuItem(translate("menu.settings.autodeobfuscation")); - miAutoDeobfuscation.setSelected(Configuration.autoDeobfuscate.get()); - miAutoDeobfuscation.addActionListener(this::autoDeobfuscate); - - miRenameOneIdentifier = new JMenuItem(translate("menu.tools.deobfuscation.globalrename")); - miRenameOneIdentifier.addActionListener(this::renameOneIdentifier); - - miRenameIdentifiers = new JMenuItem(translate("menu.tools.deobfuscation.renameinvalid")); - miRenameIdentifiers.addActionListener(this::renameIdentifiers); - - menuDeobfuscation.add(miRenameOneIdentifier); - menuDeobfuscation.add(miRenameIdentifiers); - menuDeobfuscation.add(miDeobfuscation); - JMenuItem miProxy = new JMenuItem(translate("menu.tools.proxy")); - miProxy.setIcon(View.getIcon("proxy16")); - miProxy.addActionListener(this::showProxy); - - JMenuItem miSearchMemory = new JMenuItem(translate("menu.tools.searchmemory")); - miSearchMemory.addActionListener(this::loadFromMemory); - miSearchMemory.setIcon(View.getIcon("loadmemory16")); - - JMenuItem miSearchCache = new JMenuItem(translate("menu.tools.searchcache")); - miSearchCache.addActionListener(this::loadFromCache); - miSearchCache.setIcon(View.getIcon("loadcache16")); - - miSearch = new JMenuItem(translate("menu.tools.search")); - miSearch.addActionListener((ActionEvent e) -> { - search(e, null); - }); - miSearch.setIcon(View.getIcon("search16")); - - miReplace = new JMenuItem(translate("menu.tools.replace")); - miReplace.addActionListener(this::replace); - miReplace.setIcon(View.getIcon("replace32", 16)); - - miViewTimeline = new JCheckBoxMenuItem(translate("menu.tools.timeline")); - miViewTimeline.addActionListener(this::timelineButtonActionPerformed); - miViewTimeline.setIcon(View.getIcon("timeline32", 16)); - - miGotoDocumentClass = new JMenuItem(translate("menu.tools.gotodocumentclass")); - miGotoDocumentClass.addActionListener(this::gotoDucumentClass); - - JMenu menuTools = new JMenu(translate("menu.tools")); - menuTools.add(miSearch); - menuTools.add(miReplace); - menuTools.addSeparator(); - menuTools.add(miViewTimeline); - menuTools.add(miProxy); - menuTools.add(miSearchMemory); - menuTools.add(miSearchCache); - menuTools.addSeparator(); - menuTools.add(menuDeobfuscation); - menuTools.add(menuDebugger); - menuTools.add(miGotoDocumentClass); - menuBar.add(menuTools); - - //Settings - miInternalViewer = new JCheckBoxMenuItem(translate("menu.settings.internalflashviewer")); - miInternalViewer.setSelected(Configuration.internalFlashViewer.get() || externalFlashPlayerUnavailable); - if (externalFlashPlayerUnavailable) { - miInternalViewer.setEnabled(false); + @Override + public void addToggleMenuItem(String path, String title, String group, String icon, ActionListener action, int priority) { + path = mapping(path); + String parentPath = ""; + if (path.contains("/")) { + parentPath = path.substring(0, path.lastIndexOf("/")); } - miInternalViewer.addActionListener(this::internalViewerSwitch); - - miParallelSpeedUp = new JCheckBoxMenuItem(translate("menu.settings.parallelspeedup")); - miParallelSpeedUp.setSelected(Configuration.parallelSpeedUp.get()); - miParallelSpeedUp.addActionListener(this::parallelSpeedUp); - - miDecompile = new JCheckBoxMenuItem(translate("menu.settings.disabledecompilation")); - miDecompile.setSelected(!Configuration.decompile.get()); - miDecompile.addActionListener(this::disableDecompilation); - - miCacheDisk = new JCheckBoxMenuItem(translate("menu.settings.cacheOnDisk")); - miCacheDisk.setSelected(Configuration.cacheOnDisk.get()); - miCacheDisk.addActionListener(this::cacheOnDisk); - - miGotoMainClassOnStartup = new JCheckBoxMenuItem(translate("menu.settings.gotoMainClassOnStartup")); - miGotoMainClassOnStartup.setSelected(Configuration.gotoMainClassOnStartup.get()); - miGotoMainClassOnStartup.addActionListener(this::gotoDucumentClassOnStartup); - - miAutoRenameIdentifiers = new JCheckBoxMenuItem(translate("menu.settings.autoRenameIdentifiers")); - miAutoRenameIdentifiers.setSelected(Configuration.autoRenameIdentifiers.get()); - miAutoRenameIdentifiers.addActionListener(this::autoRenameIdentifiers); - - JMenu menuSettings = new JMenu(translate("menu.settings")); - menuSettings.add(miAutoDeobfuscation); - menuSettings.add(miInternalViewer); - menuSettings.add(miParallelSpeedUp); - menuSettings.add(miDecompile); - menuSettings.add(miCacheDisk); - menuSettings.add(miGotoMainClassOnStartup); - menuSettings.add(miAutoRenameIdentifiers); - - miAssociate = new JCheckBoxMenuItem(translate("menu.settings.addtocontextmenu")); - miAssociate.addActionListener(this::associate); - miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu()); - - JMenuItem miLanguage = new JMenuItem(translate("menu.settings.language")); - miLanguage.addActionListener(this::setLanguage); - miLanguage.setIcon(View.getIcon("setlanguage32", 16)); - - if (Platform.isWindows()) { - menuSettings.add(miAssociate); + MenuElement parentMenu = menuElements.get(parentPath); + if (parentMenu == null) { + throw new IllegalArgumentException("Parent menu " + path + " does not exist"); } - menuSettings.add(miLanguage); - - miDeobfuscationModeOld = new JRadioButtonMenuItem(translate("menu.file.deobfuscation.old")); - miDeobfuscationModeOld.addActionListener((ActionEvent e) -> { - deobfuscationMode(e, 0); - }); - miDeobfuscationModeOld.setIcon(View.getIcon("deobfuscateold16")); - - miDeobfuscationModeNew = new JRadioButtonMenuItem(translate("menu.file.deobfuscation.new")); - miDeobfuscationModeNew.addActionListener((ActionEvent e) -> { - deobfuscationMode(e, 1); - }); - miDeobfuscationModeNew.setIcon(View.getIcon("deobfuscatenew16")); - - grpDeobfuscation = new ButtonGroup(); - grpDeobfuscation.add(miDeobfuscationModeOld); - grpDeobfuscation.add(miDeobfuscationModeNew); - - int deobfuscationMode = Configuration.deobfuscationMode.get(); - switch (deobfuscationMode) { - case 0: - grpDeobfuscation.clearSelection(); - miDeobfuscationModeOld.setSelected(true); - break; - case 1: - grpDeobfuscation.clearSelection(); - miDeobfuscationModeNew.setSelected(true); - break; + JMenuItem menuItem; + if (group == null) { + menuItem = new JCheckBoxMenuItem(title); + } else { + menuItem = new JRadioButtonMenuItem(title); + if (!menuGroups.containsKey(group)) { + menuGroups.put(group, new HashSet<>()); + } + if (!menuButtonGroups.containsKey(group)) { + menuButtonGroups.put(group, new ButtonGroup()); + } + menuGroups.get(group).add(path); + menuButtonGroups.get(group).add(menuItem); } + if (icon != null) { + menuItem.setIcon(View.getIcon(icon, 16)); + } + if (action != null) { + menuItem.addActionListener(action); + } + if (parentMenu instanceof JMenu) { + ((JMenu) parentMenu).add(menuItem); + } else { + throw new IllegalArgumentException("Parent path " + path + " is not a menu"); + } + menuElements.put(path, menuItem); + } - JMenu deobfuscationMenu = new JMenu(translate("menu.deobfuscation")); - deobfuscationMenu.add(miDeobfuscationModeOld); - deobfuscationMenu.add(miDeobfuscationModeNew); - menuSettings.add(deobfuscationMenu); + @Override + public String getGroupSelection(String group) { + if (!menuGroups.containsKey(group)) { + return null; + } + for (String path : menuGroups.get(group)) { + if (isMenuChecked(path)) { + return path; + } + } + return null; + } - JMenuItem advancedSettingsCommandButton = new JMenuItem(translate("menu.advancedsettings.advancedsettings")); - advancedSettingsCommandButton.setIcon(View.getIcon("settings16")); - advancedSettingsCommandButton.addActionListener(this::advancedSettings); - menuSettings.add(advancedSettingsCommandButton); - - menuBar.add(menuSettings); - JMenu menuHelp = new JMenu(translate("menu.help")); - JMenuItem miAbout = new JMenuItem(translate("menu.help.about")); - miAbout.setIcon(View.getIcon("about16")); - miAbout.addActionListener(this::about); - - JMenuItem miCheckUpdates = new JMenuItem(translate("menu.help.checkupdates")); - miCheckUpdates.setIcon(View.getIcon("update16")); - miCheckUpdates.addActionListener(this::checkUpdates); - - JMenuItem miHelpUs = new JMenuItem(translate("menu.help.helpus")); - miHelpUs.setIcon(View.getIcon("donate16")); - miHelpUs.addActionListener(this::helpUs); - - JMenuItem miHomepage = new JMenuItem(translate("menu.help.homepage")); - miHomepage.setIcon(View.getIcon("homepage16")); - miHomepage.addActionListener(this::homePage); - - menuHelp.add(miCheckUpdates); - menuHelp.add(miHelpUs); - menuHelp.add(miHomepage); - menuHelp.addSeparator(); - menuHelp.add(miAbout); - menuBar.add(menuHelp); - - mainFrame.setJMenuBar(menuBar); + @Override + public void clearMenu(String path) { + path = mapping(path); + if (path.equals("_") || path.startsWith("_/")) { + return; + } + MenuElement menu = menuElements.get(path); + if (menu == null) { + throw new IllegalArgumentException("Menu " + path + " does not exist"); + } + if (menu instanceof JMenuBar) { + ((JMenuBar) menu).removeAll(); + } else if (menu instanceof JMenu) { + ((JMenu) menu).removeAll(); + } else { + throw new IllegalArgumentException(path + " is not a menu"); + } } @Override - public void updateComponents(SWF swf) { - super.updateComponents(swf); - boolean swfLoaded = swf != null; - List abcList = swfLoaded ? swf.getAbcList() : null; - boolean hasAbc = swfLoaded && abcList != null && !abcList.isEmpty(); - boolean hasDebugger = hasAbc && DebuggerTools.hasDebugger(swf); - - miSave.setEnabled(swfLoaded); - miSaveAs.setEnabled(swfLoaded); - miSaveAsExe.setEnabled(swfLoaded); - miClose.setEnabled(swfLoaded); - miCloseAll.setEnabled(swfLoaded); - - menuExport.setEnabled(swfLoaded); - miExportAll.setEnabled(swfLoaded); - miExportFla.setEnabled(swfLoaded); - miExportSel.setEnabled(swfLoaded); - miExportXml.setEnabled(swfLoaded); - - menuImport.setEnabled(swfLoaded); - miImportText.setEnabled(swfLoaded); - miImportScript.setEnabled(swfLoaded); - miImportSymbolClass.setEnabled(swfLoaded); - miImportXml.setEnabled(swfLoaded); - - miReload.setEnabled(swfLoaded); - - miRenameIdentifiers.setEnabled(swfLoaded); - miRenameOneIdentifier.setEnabled(swfLoaded); - miSearch.setEnabled(swfLoaded); - miReplace.setEnabled(swfLoaded); - miViewTimeline.setEnabled(swfLoaded); - - miGotoDocumentClass.setEnabled(hasAbc); - miDeobfuscation.setEnabled(hasAbc); - miDebuggerSwitch.setEnabled(hasAbc); - miDebuggerSwitch.setSelected(hasDebugger); - miDebuggerReplaceTrace.setEnabled(hasAbc && hasDebugger); - } - - private void viewModeResourcesButtonActionPerformed(ActionEvent evt) { - Configuration.dumpView.set(false); - mainFrame.getPanel().showView(MainPanel.VIEW_RESOURCES); - miViewTimeline.setSelected(false); - viewGroup.clearSelection(); - miViewResources.setSelected(true); - } - - private void viewModeHexDumpButtonActionPerformed(ActionEvent evt) { - Configuration.dumpView.set(true); - mainFrame.getPanel().showView(MainPanel.VIEW_DUMP); - miViewTimeline.setSelected(false); - viewGroup.clearSelection(); - miViewHex.setSelected(true); - } - - private void debuggerSwitchButtonActionPerformed(ActionEvent evt) { - if (!miDebuggerSwitch.isSelected() || View.showConfirmDialog(mainFrame, translate("message.debugger"), translate("dialog.message.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE, Configuration.displayDebuggerInfo, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) { - switchDebugger(); - mainFrame.getPanel().refreshDecompiled(); - } else { - if (miDebuggerSwitch.isSelected()) { - miDebuggerSwitch.setSelected(false); - } + public void setMenuEnabled(String path, boolean enabled) { + path = mapping(path); + MenuElement menu = menuElements.get(path); + if (menu == null) { + throw new IllegalArgumentException("Menu " + path + " does not exist"); + } + if (menu instanceof JMenuBar) { + ((JMenuBar) menu).setEnabled(enabled); + } else if (menu instanceof JMenu) { + ((JMenu) menu).setEnabled(enabled); + } else if (menu instanceof JMenuItem) { + ((JMenuItem) menu).setEnabled(enabled); + } else { + throw new IllegalArgumentException(path + " is not a menu"); } - miDebuggerReplaceTrace.setEnabled(miDebuggerSwitch.isSelected()); } - private void timelineButtonActionPerformed(ActionEvent evt) { - if (miViewTimeline.isSelected()) { - if (!mainFrame.getPanel().showView(MainPanel.VIEW_TIMELINE)) { - miViewTimeline.setSelected(false); - } else { - viewGroup.clearSelection(); - } + @Override + public boolean isMenuChecked(String path) { + path = mapping(path); + MenuElement menu = menuElements.get(path); + if (menu == null) { + throw new IllegalArgumentException("Menu " + path + " does not exist"); + } + if (menu instanceof JCheckBoxMenuItem) { + return ((JCheckBoxMenuItem) menu).isSelected(); + } else if (menu instanceof JRadioButtonMenuItem) { + return ((JRadioButtonMenuItem) menu).isSelected(); } else { - viewGroup.clearSelection(); - if (Configuration.dumpView.get()) { - miViewHex.setSelected(true); - mainFrame.getPanel().showView(MainPanel.VIEW_DUMP); - } else { - miViewResources.setSelected(true); - mainFrame.getPanel().showView(MainPanel.VIEW_RESOURCES); + throw new IllegalArgumentException(path + " is not selectable menu item"); + } + } + + @Override + public void setMenuChecked(String path, boolean checked) { + path = mapping(path); + MenuElement menu = menuElements.get(path); + if (menu == null) { + throw new IllegalArgumentException("Menu " + path + " does not exist"); + } + if (menu instanceof JCheckBoxMenuItem) { + ((JCheckBoxMenuItem) menu).setSelected(checked); + } else if (menu instanceof JRadioButtonMenuItem) { + ((JRadioButtonMenuItem) menu).setSelected(checked); + } else { + throw new IllegalArgumentException(path + " is not selectable menu item"); + } + } + + @Override + public void setGroupSelection(String group, String selected) { + selected = mapping(selected); + for (String path : menuGroups.get(group)) { + setMenuChecked(path, path.equals(selected)); + } + } + + @Override + public void initMenu() { + JMenuBar menuBar = new JMenuBar(); + menuElements.put("", menuBar); + mainFrame.setJMenuBar(menuBar); + } + + @Override + public void finishMenu(String path) { + path = mapping(path); + if (path.equals("_") || path.startsWith("_/")) { + return; + } + if (!menuElements.containsKey(path)) { + throw new IllegalArgumentException("Invalid menu: " + path); + } + MenuElement me = menuElements.get(path); + if (me instanceof JMenu) { + JMenu jm = (JMenu) me; + if (jm.getMenuComponentCount() == 1) { + String parentPath = path.contains("/") ? path.substring(0, path.lastIndexOf("/")) : ""; + MenuElement parMe = menuElements.get(parentPath); + JMenuItem mi = (JMenuItem) jm.getMenuComponent(0); + jm.remove(mi); + if (parMe instanceof JMenu) { + JMenu parMenu = (JMenu) parMe; + parMenu.remove(jm); + parMenu.add(mi); + } else if (parMe instanceof JMenuBar) { + JMenuBar parMenuBar = (JMenuBar) parMe; + parMenuBar.remove(jm); + parMenuBar.add(mi); + } } } } + + @Override + public void addSeparator(String parentPath) { + parentPath = mapping(parentPath); + if (parentPath.equals("_") || parentPath.startsWith("_/")) { + return; + } + if (!menuElements.containsKey(parentPath)) { + throw new IllegalArgumentException("Menu does not exist: " + parentPath); + } + MenuElement parent = menuElements.get(parentPath); + if (parent instanceof JMenu) { + ((JMenu) parent).addSeparator(); + } else { + throw new IllegalArgumentException("Not a menu: " + parentPath); + } + } + + @Override + public boolean supportsMenuAction() { + return false; + } + + @Override + public boolean supportsAppMenu() { + return false; + } + + /** + * Maps some menus to other location + * + * @param s Source + * @return To + */ + private String mapping(String s) { + Map map = new HashMap<>(); + map.put("/file/view", "/view"); + + for (String k : map.keySet()) { + String v = map.get(k); + if (s.startsWith(k)) { + s = v + s.substring(k.length()); + return s; + } + } + return s; + } + } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index cb310907e..9565791d1 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -1,634 +1,961 @@ -/* - * Copyright (C) 2010-2015 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.ApplicationInfo; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.console.ContextMenuTools; -import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; -import com.jpexs.decompiler.flash.gui.helpers.CheckResources; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.Cache; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.KeyEventDispatcher; -import java.awt.KeyboardFocusManager; -import java.awt.ScrollPane; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowEvent; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Timer; -import java.util.TimerTask; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.AbstractButton; -import javax.swing.JDialog; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JOptionPane; - -/** - * - * @author JPEXS - */ -public abstract class MainFrameMenu { - - private final MainFrame mainFrame; - - private SWF swf; - - public abstract boolean isInternalFlashViewerSelected(); - - public MainFrameMenu(MainFrame mainFrame) { - registerHotKeys(); - this.mainFrame = mainFrame; - } - - protected String translate(String key) { - return mainFrame.translate(key); - } - - protected boolean open(ActionEvent evt) { - if (Main.isWorking()) { - return false; - } - - Main.openFileDialog(); - return true; - } - - protected boolean save(ActionEvent evt) { - if (Main.isWorking()) { - return false; - } - - if (swf != null) { - boolean saved = false; - if (swf.swfList != null && swf.swfList.isBundle()) { - SWFBundle bundle = swf.swfList.bundle; - if (!bundle.isReadOnly()) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - swf.saveTo(baos); - saved = bundle.putSWF(swf.getFileTitle(), new ByteArrayInputStream(baos.toByteArray())); - } catch (IOException ex) { - Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); - } - } - } else if (swf.binaryData != null) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - swf.saveTo(baos); - swf.binaryData.binaryData = new ByteArrayRange(baos.toByteArray()); - swf.binaryData.setModified(true); - saved = true; - } catch (IOException ex) { - Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); - } - } else if (swf.getFile() == null) { - saved = saveAs(swf, SaveFileMode.SAVEAS); - } else { - try { - Main.saveFile(swf, swf.getFile()); - saved = true; - } catch (IOException ex) { - Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, null, ex); - View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE); - } - } - if (saved) { - swf.clearModified(); - mainFrame.getPanel().refreshTree(swf); - } - - return true; - } - - return false; - } - - protected boolean saveAs(ActionEvent evt) { - if (Main.isWorking()) { - return false; - } - - if (swf != null) { - if (saveAs(swf, SaveFileMode.SAVEAS)) { - swf.clearModified(); - } - - return true; - } - - return false; - } - - private boolean saveAs(SWF swf, SaveFileMode mode) { - if (Main.saveFileDialog(swf, mode)) { - mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : "")); - updateComponents(swf); - return true; - } - return false; - } - - protected void saveAsExe(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - if (swf != null) { - saveAs(swf, SaveFileMode.EXE); - } - } - - protected void close(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - if (swf == null) { - return; - } - - Main.closeFile(swf.swfList); - } - - protected boolean closeAll(ActionEvent evt) { - if (Main.isWorking()) { - return false; - } - - if (swf != null) { - Main.closeAll(); - return true; - } - - return false; - } - - protected void importText(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().importText(swf); - } - - protected void importScript(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().importScript(swf); - } - - protected void importSymbolClass(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().importSymbolClass(swf); - } - - protected void exportAll(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - export(false); - } - - protected void exportSelected(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - export(true); - } - - protected boolean export(boolean onlySelected) { - if (swf != null) { - mainFrame.getPanel().export(onlySelected); - return true; - } - - return false; - } - - protected void exportFla(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().exportFla(swf); - } - - protected void importSwfXml(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().importSwfXml(); - } - - protected void exportSwfXml(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().exportSwfXml(); - } - - protected boolean search(ActionEvent evt, Boolean searchInText) { - if (swf != null) { - mainFrame.getPanel().searchInActionScriptOrText(searchInText); - return true; - } - - return false; - } - - protected boolean replace(ActionEvent evt) { - if (swf != null) { - mainFrame.getPanel().replaceText(); - return true; - } - - return false; - } - - protected void restoreControlFlow(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - restoreControlFlow(false); - } - - protected void restoreControlFlowAll(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - restoreControlFlow(true); - } - - protected void restoreControlFlow(boolean all) { - mainFrame.getPanel().restoreControlFlow(all); - } - - protected void showProxy(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - Main.showProxy(); - } - - protected boolean clearLog() { - ErrorLogFrame.getInstance().clearLog(); - return true; - } - - protected void renameOneIdentifier(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().renameOneIdentifier(swf); - } - - protected void renameIdentifiers(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().renameIdentifiers(swf); - } - - protected void deobfuscate(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - mainFrame.getPanel().deobfuscate(); - } - - protected void setSubLimiter(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - Main.setSubLimiter(selected); - } - - protected void switchDebugger() { - DebuggerTools.switchDebugger(swf); - } - - protected void debuggerShowLog(ActionEvent evt) { - DebuggerTools.debuggerShowLog(); - } - - protected void debuggerReplaceTraceCalls(ActionEvent evt) { - ReplaceTraceDialog rtd = new ReplaceTraceDialog(Configuration.lastDebuggerReplaceFunction.get()); - rtd.setVisible(true); - if (rtd.getValue() != null) { - String fname = rtd.getValue(); - DebuggerTools.replaceTraceCalls(swf, fname); - mainFrame.getPanel().refreshDecompiled(); - Configuration.lastDebuggerReplaceFunction.set(rtd.getValue()); - } - } - - protected void clearRecentFiles(ActionEvent evt) { - Configuration.recentFiles.set(null); - } - - protected void removeNonScripts() { - mainFrame.getPanel().removeNonScripts(swf); - } - - protected void refreshDecompiled() { - mainFrame.getPanel().refreshDecompiled(); - } - - protected boolean previousTag() { - return mainFrame.getPanel().previousTag(); - } - - protected boolean nextTag() { - return mainFrame.getPanel().nextTag(); - } - - protected void checkResources() { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - PrintStream stream = new PrintStream(os); - CheckResources.checkResources(stream); - final String str = new String(os.toByteArray(), Utf8Helper.charset); - JDialog dialog = new JDialog() { - - @Override - public void setVisible(boolean bln) { - setSize(new Dimension(800, 600)); - Container cnt = getContentPane(); - cnt.setLayout(new BorderLayout()); - ScrollPane scrollPane = new ScrollPane(); - JEditorPane editor = new JEditorPane(); - editor.setEditable(false); - editor.setText(str); - scrollPane.add(editor); - this.add(scrollPane, BorderLayout.CENTER); - this.setModal(true); - View.centerScreen(this); - super.setVisible(bln); - } - }; - dialog.setVisible(true); - } - - protected void checkUpdates(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - if (!Main.checkForUpdates()) { - View.showMessageDialog(null, translate("update.check.nonewversion"), translate("update.check.title"), JOptionPane.INFORMATION_MESSAGE); - } - } - - protected void helpUs(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - String helpUsURL = ApplicationInfo.PROJECT_PAGE + "/help_us.html?utm_source=app&utm_medium=menu&utm_campaign=app"; - if (!View.navigateUrl(helpUsURL)) { - View.showMessageDialog(null, translate("message.helpus").replace("%url%", helpUsURL)); - } - } - - protected void homePage(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - String homePageURL = ApplicationInfo.PROJECT_PAGE + "?utm_source=app&utm_medium=menu&utm_campaign=app"; - if (!View.navigateUrl(homePageURL)) { - View.showMessageDialog(null, translate("message.homepage").replace("%url%", homePageURL)); - } - } - - protected void about(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - Main.about(); - } - - protected boolean reload(ActionEvent evt) { - if (swf != null) { - if (View.showConfirmDialog(null, translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { - Main.reloadApp(); - } - - return true; - } - - return false; - } - - protected void advancedSettings(ActionEvent evt) { - Main.advancedSettings(); - } - - protected void loadFromMemory(ActionEvent evt) { - Main.loadFromMemory(); - } - - protected void loadFromCache(ActionEvent evt) { - Main.loadFromCache(); - } - - protected void gotoDucumentClassOnStartup(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - Configuration.gotoMainClassOnStartup.set(selected); - } - - protected void autoRenameIdentifiers(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - Configuration.autoRenameIdentifiers.set(selected); - } - - protected void cacheOnDisk(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - Configuration.cacheOnDisk.set(selected); - if (selected) { - Cache.setStorageType(Cache.STORAGE_FILES); - } else { - Cache.setStorageType(Cache.STORAGE_MEMORY); - } - } - - protected void setLanguage(ActionEvent evt) { - new SelectLanguageDialog().display(); - } - - protected void disableDecompilation(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - Configuration.decompile.set(!selected); - mainFrame.getPanel().disableDecompilationChanged(); - } - - protected void associate(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - if (selected == ContextMenuTools.isAddedToContextMenu()) { - return; - } - ContextMenuTools.addToContextMenu(selected, false); - - // Update checkbox menuitem accordingly (User can cancel rights elevation) - new Timer().schedule(new TimerTask() { - @Override - public void run() { - button.setSelected(ContextMenuTools.isAddedToContextMenu()); - } - }, 1000); // It takes some time registry change to apply - } - - protected void gotoDucumentClass(ActionEvent evt) { - mainFrame.getPanel().gotoDocumentClass(mainFrame.getPanel().getCurrentSwf()); - } - - protected void parallelSpeedUp(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - String confStr = translate("message.confirm.parallel") + "\r\n"; - if (selected) { - 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(selected); - } else { - button.setSelected(Configuration.parallelSpeedUp.get()); - } - } - - protected void internalViewerSwitch(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - Configuration.internalFlashViewer.set(selected); - mainFrame.getPanel().reload(true); - } - - protected void autoDeobfuscate(ActionEvent evt) { - AbstractButton button = (AbstractButton) evt.getSource(); - boolean selected = button.isSelected(); - - if (View.showConfirmDialog(mainFrame.getPanel(), translate("message.confirm.autodeobfuscate") + "\r\n" + (selected ? translate("message.confirm.on") : translate("message.confirm.off")), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { - Configuration.autoDeobfuscate.set(selected); - mainFrame.getPanel().autoDeobfuscateChanged(); - } else { - button.setSelected(Configuration.autoDeobfuscate.get()); - } - } - - protected void deobfuscationMode(ActionEvent evt, int mode) { - Configuration.deobfuscationMode.set(mode); - mainFrame.getPanel().autoDeobfuscateChanged(); - } - - protected void exit(ActionEvent evt) { - JFrame frame = (JFrame) mainFrame; - frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); - } - - public void updateComponents(SWF swf) { - this.swf = swf; - } - - private void registerHotKeys() { - - KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - manager.addKeyEventDispatcher(new KeyEventDispatcher() { - - @Override - public boolean dispatchKeyEvent(KeyEvent e) { - if (((JFrame) mainFrame).isActive() && e.getID() == KeyEvent.KEY_PRESSED) { - int code = e.getKeyCode(); - if (e.isControlDown() && e.isShiftDown()) { - switch (code) { - case KeyEvent.VK_O: - return open(null); - case KeyEvent.VK_S: - return save(null); - case KeyEvent.VK_A: - return saveAs(null); - case KeyEvent.VK_F: - return search(null, false); - case KeyEvent.VK_T: - return search(null, true); - case KeyEvent.VK_R: - return reload(null); - case KeyEvent.VK_X: - return closeAll(null); - case KeyEvent.VK_D: - return clearLog(); - case KeyEvent.VK_E: - return export(false); - } - } else if (e.isControlDown() && !e.isShiftDown()) { - switch (code) { - case KeyEvent.VK_UP: - return previousTag(); - case KeyEvent.VK_DOWN: - return nextTag(); - } - } - } - - return false; - } - }); - } -} +/* + * Copyright (C) 2010-2015 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.ApplicationInfo; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFBundle; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.console.ContextMenuTools; +import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; +import com.jpexs.decompiler.flash.gui.helpers.CheckResources; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.Cache; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.utf8.Utf8Helper; +import com.sun.jna.Platform; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.KeyboardFocusManager; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.AbstractButton; +import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +/** + * + * @author JPEXS + */ +public abstract class MainFrameMenu implements MenuBuilder { + + private final MainFrame mainFrame; + + private SWF swf; + + public boolean isInternalFlashViewerSelected() { + return isMenuChecked("/settings/internalViewer"); //miInternalViewer.isSelected(); + } + + private boolean externalFlashPlayerUnavailable; + + public MainFrameMenu(MainFrame mainFrame, boolean externalFlashPlayerUnavailable) { + registerHotKeys(); + this.mainFrame = mainFrame; + this.externalFlashPlayerUnavailable = externalFlashPlayerUnavailable; + } + + protected String translate(String key) { + return mainFrame.translate(key); + } + + protected boolean open(ActionEvent evt) { + if (Main.isWorking()) { + return false; + } + + Main.openFileDialog(); + return true; + } + + protected boolean save(ActionEvent evt) { + if (Main.isWorking()) { + return false; + } + + if (swf != null) { + boolean saved = false; + if (swf.swfList != null && swf.swfList.isBundle()) { + SWFBundle bundle = swf.swfList.bundle; + if (!bundle.isReadOnly()) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + swf.saveTo(baos); + saved = bundle.putSWF(swf.getFileTitle(), new ByteArrayInputStream(baos.toByteArray())); + } catch (IOException ex) { + Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); + } + } + } else if (swf.binaryData != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + swf.saveTo(baos); + swf.binaryData.binaryData = new ByteArrayRange(baos.toByteArray()); + swf.binaryData.setModified(true); + saved = true; + } catch (IOException ex) { + Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); + } + } else if (swf.getFile() == null) { + saved = saveAs(swf, SaveFileMode.SAVEAS); + } else { + try { + Main.saveFile(swf, swf.getFile()); + saved = true; + } catch (IOException ex) { + Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, null, ex); + View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE); + } + } + if (saved) { + swf.clearModified(); + mainFrame.getPanel().refreshTree(swf); + } + + return true; + } + + return false; + } + + protected boolean saveAs(ActionEvent evt) { + if (Main.isWorking()) { + return false; + } + + if (swf != null) { + if (saveAs(swf, SaveFileMode.SAVEAS)) { + swf.clearModified(); + } + + return true; + } + + return false; + } + + private boolean saveAs(SWF swf, SaveFileMode mode) { + if (Main.saveFileDialog(swf, mode)) { + mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : "")); + updateComponents(swf); + return true; + } + return false; + } + + protected void saveAsExe(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + if (swf != null) { + saveAs(swf, SaveFileMode.EXE); + } + } + + protected void close(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + if (swf == null) { + return; + } + + Main.closeFile(swf.swfList); + } + + protected boolean closeAll(ActionEvent evt) { + if (Main.isWorking()) { + return false; + } + + if (swf != null) { + Main.closeAll(); + return true; + } + + return false; + } + + protected void importText(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().importText(swf); + } + + protected void importScript(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().importScript(swf); + } + + protected void importSymbolClass(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().importSymbolClass(swf); + } + + protected void exportAll(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + export(false); + } + + protected void exportSelected(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + export(true); + } + + protected boolean export(boolean onlySelected) { + if (swf != null) { + mainFrame.getPanel().export(onlySelected); + return true; + } + + return false; + } + + protected void exportFla(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().exportFla(swf); + } + + protected void importSwfXml(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().importSwfXml(); + } + + protected void exportSwfXml(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().exportSwfXml(); + } + + protected boolean search(ActionEvent evt, Boolean searchInText) { + if (swf != null) { + mainFrame.getPanel().searchInActionScriptOrText(searchInText); + return true; + } + + return false; + } + + protected boolean replace(ActionEvent evt) { + if (swf != null) { + mainFrame.getPanel().replaceText(); + return true; + } + + return false; + } + + protected void restoreControlFlow(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + restoreControlFlow(false); + } + + protected void restoreControlFlowAll(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + restoreControlFlow(true); + } + + protected void restoreControlFlow(boolean all) { + mainFrame.getPanel().restoreControlFlow(all); + } + + protected void showProxy(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + Main.showProxy(); + } + + protected boolean clearLog() { + ErrorLogFrame.getInstance().clearLog(); + return true; + } + + protected void renameOneIdentifier(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().renameOneIdentifier(swf); + } + + protected void renameIdentifiers(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().renameIdentifiers(swf); + } + + protected void deobfuscate(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + mainFrame.getPanel().deobfuscate(); + } + + protected void setSubLimiter(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + Main.setSubLimiter(selected); + } + + protected void switchDebugger() { + DebuggerTools.switchDebugger(swf); + } + + protected void debuggerShowLog(ActionEvent evt) { + DebuggerTools.debuggerShowLog(); + } + + protected void debuggerReplaceTraceCalls(ActionEvent evt) { + ReplaceTraceDialog rtd = new ReplaceTraceDialog(Configuration.lastDebuggerReplaceFunction.get()); + rtd.setVisible(true); + if (rtd.getValue() != null) { + String fname = rtd.getValue(); + DebuggerTools.replaceTraceCalls(swf, fname); + mainFrame.getPanel().refreshDecompiled(); + Configuration.lastDebuggerReplaceFunction.set(rtd.getValue()); + } + } + + protected void clearRecentFiles(ActionEvent evt) { + Configuration.recentFiles.set(null); + } + + protected void removeNonScripts() { + mainFrame.getPanel().removeNonScripts(swf); + } + + protected void refreshDecompiled() { + mainFrame.getPanel().refreshDecompiled(); + } + + protected boolean previousTag() { + return mainFrame.getPanel().previousTag(); + } + + protected boolean nextTag() { + return mainFrame.getPanel().nextTag(); + } + + protected void checkResources() { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + PrintStream stream = new PrintStream(os); + CheckResources.checkResources(stream); + final String str = new String(os.toByteArray(), Utf8Helper.charset); + JDialog dialog = new JDialog() { + + @Override + public void setVisible(boolean bln) { + setSize(new Dimension(800, 600)); + Container cnt = getContentPane(); + cnt.setLayout(new BorderLayout()); + ScrollPane scrollPane = new ScrollPane(); + JEditorPane editor = new JEditorPane(); + editor.setEditable(false); + editor.setText(str); + scrollPane.add(editor); + this.add(scrollPane, BorderLayout.CENTER); + this.setModal(true); + View.centerScreen(this); + super.setVisible(bln); + } + }; + dialog.setVisible(true); + } + + protected void checkUpdates(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + if (!Main.checkForUpdates()) { + View.showMessageDialog(null, translate("update.check.nonewversion"), translate("update.check.title"), JOptionPane.INFORMATION_MESSAGE); + } + } + + protected void helpUs(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + String helpUsURL = ApplicationInfo.PROJECT_PAGE + "/help_us.html?utm_source=app&utm_medium=menu&utm_campaign=app"; + if (!View.navigateUrl(helpUsURL)) { + View.showMessageDialog(null, translate("message.helpus").replace("%url%", helpUsURL)); + } + } + + protected void homePage(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + String homePageURL = ApplicationInfo.PROJECT_PAGE + "?utm_source=app&utm_medium=menu&utm_campaign=app"; + if (!View.navigateUrl(homePageURL)) { + View.showMessageDialog(null, translate("message.homepage").replace("%url%", homePageURL)); + } + } + + protected void about(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + Main.about(); + } + + protected boolean reload(ActionEvent evt) { + if (swf != null) { + if (View.showConfirmDialog(null, translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { + Main.reloadApp(); + } + + return true; + } + + return false; + } + + protected void advancedSettings(ActionEvent evt) { + Main.advancedSettings(); + } + + protected void loadFromMemory(ActionEvent evt) { + Main.loadFromMemory(); + } + + protected void loadFromCache(ActionEvent evt) { + Main.loadFromCache(); + } + + protected void gotoDucumentClassOnStartup(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + Configuration.gotoMainClassOnStartup.set(selected); + } + + protected void autoRenameIdentifiers(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + Configuration.autoRenameIdentifiers.set(selected); + } + + protected void cacheOnDisk(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + Configuration.cacheOnDisk.set(selected); + if (selected) { + Cache.setStorageType(Cache.STORAGE_FILES); + } else { + Cache.setStorageType(Cache.STORAGE_MEMORY); + } + } + + protected void setLanguage(ActionEvent evt) { + new SelectLanguageDialog().display(); + } + + protected void disableDecompilation(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + Configuration.decompile.set(!selected); + mainFrame.getPanel().disableDecompilationChanged(); + } + + protected void associate(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + if (selected == ContextMenuTools.isAddedToContextMenu()) { + return; + } + ContextMenuTools.addToContextMenu(selected, false); + + // Update checkbox menuitem accordingly (User can cancel rights elevation) + new Timer().schedule(new TimerTask() { + @Override + public void run() { + button.setSelected(ContextMenuTools.isAddedToContextMenu()); + } + }, 1000); // It takes some time registry change to apply + } + + protected void gotoDucumentClass(ActionEvent evt) { + mainFrame.getPanel().gotoDocumentClass(mainFrame.getPanel().getCurrentSwf()); + } + + protected void parallelSpeedUp(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + String confStr = translate("message.confirm.parallel") + "\r\n"; + if (selected) { + 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(selected); + } else { + button.setSelected(Configuration.parallelSpeedUp.get()); + } + } + + protected void internalViewerSwitch(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + Configuration.internalFlashViewer.set(selected); + mainFrame.getPanel().reload(true); + } + + protected void autoDeobfuscate(ActionEvent evt) { + AbstractButton button = (AbstractButton) evt.getSource(); + boolean selected = button.isSelected(); + + if (View.showConfirmDialog(mainFrame.getPanel(), translate("message.confirm.autodeobfuscate") + "\r\n" + (selected ? translate("message.confirm.on") : translate("message.confirm.off")), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { + Configuration.autoDeobfuscate.set(selected); + mainFrame.getPanel().autoDeobfuscateChanged(); + } else { + button.setSelected(Configuration.autoDeobfuscate.get()); + } + } + + protected void deobfuscationMode(ActionEvent evt, int mode) { + Configuration.deobfuscationMode.set(mode); + mainFrame.getPanel().autoDeobfuscateChanged(); + } + + protected void exit(ActionEvent evt) { + JFrame frame = (JFrame) mainFrame; + frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); + } + + public void updateComponents(SWF swf) { + this.swf = swf; + boolean swfLoaded = swf != null; + List abcList = swf != null ? swf.getAbcList() : null; + boolean hasAbc = swfLoaded && abcList != null && !abcList.isEmpty(); + boolean hasDebugger = hasAbc && DebuggerTools.hasDebugger(swf); + + setMenuEnabled("/file/save", swfLoaded); + setMenuEnabled("/file/saveAs", swfLoaded); + setMenuEnabled("/file/saveAsExe", swfLoaded); + setMenuEnabled("/file/close", swfLoaded); + setMenuEnabled("/file/closeAll", swfLoaded); + + setMenuEnabled("/file/export", swfLoaded); + setMenuEnabled("/file/export/exportAll", swfLoaded); + setMenuEnabled("/file/export/exportFla", swfLoaded); + setMenuEnabled("/file/export/exportSel", swfLoaded); + setMenuEnabled("/file/export/exportXml", swfLoaded); + + setMenuEnabled("/file/import", swfLoaded); + setMenuEnabled("/file/import/importText", swfLoaded); + setMenuEnabled("/file/import/importScript", swfLoaded); + setMenuEnabled("/file/import/importSymbolClass", swfLoaded); + setMenuEnabled("/file/import/importXml", swfLoaded); + + setMenuEnabled("/file/reload", swfLoaded); + + setMenuEnabled("/tools/deobfuscation", swfLoaded); + setMenuEnabled("/tools/deobfuscation/renameOneIdentifier", swfLoaded); + setMenuEnabled("/tools/deobfuscation/renameInvalidIdentifiers", swfLoaded); + setMenuEnabled("/tools/deobfuscation/deobfuscation", hasAbc); + + setMenuEnabled("/tools/search", swfLoaded); + setMenuEnabled("/tools/replace", swfLoaded); + setMenuEnabled("/tools/timeline", swfLoaded); + + setMenuEnabled("/tools/gotodocumentclass", hasAbc); + setMenuEnabled("/tools/debugger/debuggerSwitch", hasAbc); + setMenuChecked("/tools/debugger/debuggerSwitch", hasDebugger); + setMenuEnabled("/tools/debugger/debuggerReplaceTrace", hasAbc && hasDebugger); + + } + + private void registerHotKeys() { + + KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + manager.addKeyEventDispatcher((KeyEvent e) -> { + if (((JFrame) mainFrame).isActive() && e.getID() == KeyEvent.KEY_PRESSED) { + int code = e.getKeyCode(); + if (e.isControlDown() && e.isShiftDown()) { + switch (code) { + case KeyEvent.VK_O: + return open(null); + case KeyEvent.VK_S: + return save(null); + case KeyEvent.VK_A: + return saveAs(null); + case KeyEvent.VK_F: + return search(null, false); + case KeyEvent.VK_T: + return search(null, true); + case KeyEvent.VK_R: + return reload(null); + case KeyEvent.VK_X: + return closeAll(null); + case KeyEvent.VK_D: + return clearLog(); + case KeyEvent.VK_E: + return export(false); + } + } else if (e.isControlDown() && !e.isShiftDown()) { + switch (code) { + case KeyEvent.VK_UP: + return previousTag(); + case KeyEvent.VK_DOWN: + return nextTag(); + } + } + } + + return false; + }); + } + + public void createMenuBar() { + initMenu(); + if (supportsAppMenu()) { + addMenuItem("_", null, null, null, 0, null, false); + addMenuItem("_/open", translate("menu.file.open"), "open32", this::open, PRIORITY_TOP, this::loadRecent, false); + addMenuItem("_/save", translate("menu.file.save"), "save32", this::save, PRIORITY_TOP, null, true); + addMenuItem("_/saveAs", translate("menu.file.saveas"), "saveas32", this::saveAs, PRIORITY_TOP, null, true); + addSeparator("_"); + addMenuItem("_/exportFla", translate("menu.file.export.fla"), "exportfla32", this::exportFla, PRIORITY_TOP, null, true); + addMenuItem("_/exportAll", translate("menu.file.export.all"), "export32", this::exportAll, PRIORITY_TOP, null, true); + addMenuItem("_/exportSel", translate("menu.file.export.selection"), "exportsel32", this::exportSelected, PRIORITY_TOP, null, true); + addSeparator("_"); + addMenuItem("_/checkUpdates", translate("menu.help.checkupdates"), "update32", this::checkUpdates, PRIORITY_TOP, null, true); + addMenuItem("_/about", translate("menu.help.about"), "about32", this::about, PRIORITY_TOP, null, true); + addMenuItem("_/close", translate("menu.file.close"), "close32", this::close, PRIORITY_TOP, null, true); + addMenuItem("_/closeAll", translate("menu.file.closeAll"), "close32", this::closeAll, PRIORITY_TOP, null, true); + addMenuItem("_/$exit", translate("menu.file.exit"), "exit32", this::exit, PRIORITY_TOP, null, true); + finishMenu("_"); + } + + addMenuItem("/file", translate("menu.file"), null, null, 0, null, false); + addMenuItem("/file/open", translate("menu.file.open"), "open32", this::open, PRIORITY_TOP, this::loadRecent, !supportsMenuAction()); + + if (!supportsMenuAction()) { + addMenuItem("/file/recent", translate("menu.recentFiles"), null, null, 0, this::loadRecent, false); + finishMenu("/file/recent"); + } else { + finishMenu("/file/open"); + } + addMenuItem("/file/save", translate("menu.file.save"), "save32", this::save, PRIORITY_TOP, null, true); + addMenuItem("/file/saveAs", translate("menu.file.saveas"), "saveas16", this::saveAs, PRIORITY_MEDIUM, null, true); + addMenuItem("/file/saveAsExe", translate("menu.file.saveasexe"), "saveasexe16", this::saveAsExe, PRIORITY_MEDIUM, null, true); + addMenuItem("/file/reload", translate("menu.file.reload"), "reload16", this::reload, PRIORITY_MEDIUM, null, true); + + addSeparator("/file"); + + addMenuItem("/file/export", translate("menu.export"), null, null, 0, null, false); + addMenuItem("/file/export/exportFla", translate("menu.file.export.fla"), "exportfla32", this::exportFla, PRIORITY_TOP, null, true); + addMenuItem("/file/export/exportXml", translate("menu.file.export.xml"), "exportxml32", this::exportSelected, PRIORITY_MEDIUM, null, true); + + addMenuItem("/file/export/exportAll", translate("menu.file.export.all"), "export16", this::exportAll, PRIORITY_MEDIUM, null, true); + addMenuItem("/file/export/exportSel", translate("menu.file.export.selection"), "exportsel16", this::exportSelected, PRIORITY_MEDIUM, null, true); + finishMenu("/file/export"); + + addMenuItem("/file/import", translate("menu.import"), null, null, 0, null, false); + addMenuItem("/file/import/importXml", translate("menu.file.import.xml"), "importxml32", this::importSwfXml, PRIORITY_TOP, null, true); + addMenuItem("/file/import/importText", translate("menu.file.import.text"), "importtext32", this::importText, PRIORITY_MEDIUM, null, true); + addMenuItem("/file/import/importScript", translate("menu.file.import.script"), "importtext32", this::importScript, PRIORITY_MEDIUM, null, true); + addMenuItem("/file/import/importSymbolClass", translate("menu.file.import.symbolClass"), "importsymbolclass32", this::importSymbolClass, PRIORITY_MEDIUM, null, true); + finishMenu("/file/import"); + + addSeparator("/file"); + + addMenuItem("/file/view", translate("menu.view"), null, null, 0, null, false); + addToggleMenuItem("/file/view/viewResources", translate("menu.file.view.resources"), "view", "viewresources16", this::viewModeResourcesButtonActionPerformed, PRIORITY_MEDIUM); + addToggleMenuItem("/file/view/viewHex", translate("menu.file.view.hex"), "view", "viewhex16", this::viewModeHexDumpButtonActionPerformed, PRIORITY_MEDIUM); + finishMenu("/file/view"); + + addSeparator("/file"); + addMenuItem("/file/close", translate("menu.file.close"), "close32", this::close, PRIORITY_MEDIUM, null, true); + addMenuItem("/file/closeAll", translate("menu.file.closeAll"), "close32", this::closeAll, PRIORITY_MEDIUM, null, true); + + if (!supportsAppMenu()) { + addMenuItem("/file/exit", translate("menu.file.exit"), "exit32", this::exit, PRIORITY_TOP, null, true); + } + finishMenu("/file"); + + if (Configuration.dumpView.get()) { + setGroupSelection("view", "/file/view/viewHex"); + } else { + setGroupSelection("view", "/file/view/viewResources"); + } + + addMenuItem("/tools", translate("menu.tools"), null, null, 0, null, false); + addMenuItem("/tools/search", translate("menu.tools.search"), "search16", (ActionEvent e) -> { + search(e, null); + }, PRIORITY_TOP, null, true); + + addMenuItem("/tools/replace", translate("menu.tools.replace"), "replace32", this::replace, PRIORITY_TOP, null, true); + addToggleMenuItem("/tools/timeline", translate("menu.tools.timeline"), null, "timeline32", this::timelineButtonActionPerformed, PRIORITY_TOP); + + addMenuItem("/tools/proxy", translate("menu.tools.proxy"), "proxy16", this::showProxy, PRIORITY_MEDIUM, null, true); + addMenuItem("/tools/searchmemory", translate("menu.tools.searchmemory"), "loadmemory16", this::loadFromMemory, PRIORITY_MEDIUM, null, true); + addMenuItem("/tools/searchcache", translate("menu.tools.searchcache"), "loadcache16", this::loadFromCache, PRIORITY_MEDIUM, null, true); + + addMenuItem("/tools/deobfuscation", translate("menu.tools.deobfuscation"), "deobfuscate16", null, 0, null, false); + addMenuItem("/tools/deobfuscation/renameOneIdentifier", translate("menu.tools.deobfuscation.globalrename"), "rename16", this::renameOneIdentifier, PRIORITY_MEDIUM, null, true); + addMenuItem("/tools/deobfuscation/renameInvalidIdentifiers", translate("menu.tools.deobfuscation.renameinvalid"), "renameall16", this::renameIdentifiers, PRIORITY_MEDIUM, null, true); + addMenuItem("/tools/deobfuscation/deobfuscation", translate("menu.tools.deobfuscation.pcode"), "deobfuscate32", this::deobfuscate, PRIORITY_TOP, null, true); + finishMenu("/tools/deobfuscation"); + + addMenuItem("/tools/debugger", translate("menu.debugger"), null, null, 0, null, false); + addToggleMenuItem("/tools/debugger/debuggerSwitch", translate("menu.debugger.switch"), null, "debugger32", this::debuggerSwitchButtonActionPerformed, PRIORITY_TOP); + addMenuItem("/tools/debugger/debuggerReplaceTrace", translate("menu.debugger.replacetrace"), "debuggerreplace16", this::debuggerReplaceTraceCalls, PRIORITY_MEDIUM, null, true); + addMenuItem("/tools/debugger/debuggerShowLog", translate("menu.debugger.showlog"), "debuggerlog16", this::debuggerShowLog, PRIORITY_MEDIUM, null, true); + finishMenu("/tools/debugger"); + + addMenuItem("/tools/gotodocumentclass", translate("menu.tools.gotodocumentclass"), "gotomainclass32", this::gotoDucumentClass, PRIORITY_TOP, null, true); + finishMenu("/tools"); + + //Settings + addMenuItem("/settings", translate("menu.settings"), null, null, 0, null, false); + + addToggleMenuItem("/settings/autodeobfuscation", translate("menu.settings.autodeobfuscation"), null, null, this::autoDeobfuscate, 0); + + addToggleMenuItem("/settings/internalViewer", translate("menu.settings.internalflashviewer"), null, null, this::internalViewerSwitch, 0); + + addToggleMenuItem("/settings/parallelspeedup", translate("menu.settings.parallelspeedup"), null, null, this::parallelSpeedUp, 0); + + addToggleMenuItem("/settings/disableDecompilation", translate("menu.settings.disabledecompilation"), null, null, this::disableDecompilation, 0); + + addToggleMenuItem("/settings/cacheOnDisk", translate("menu.settings.cacheOnDisk"), null, null, this::cacheOnDisk, 0); + + addToggleMenuItem("/settings/gotoMainClassOnStartup", translate("menu.settings.gotoMainClassOnStartup"), null, null, this::gotoDucumentClassOnStartup, 0); + + addToggleMenuItem("/settings/autoRenameIdentifiers", translate("menu.settings.autoRenameIdentifiers"), null, null, this::autoRenameIdentifiers, 0); + + if (Platform.isWindows()) { + addToggleMenuItem("/settings/associate", translate("menu.settings.addtocontextmenu"), null, null, this::associate, 0); + } + addMenuItem("/settings/language", translate("menu.language"), null, null, 0, null, false); + addMenuItem("/settings/language/setlanguage", translate("menu.settings.language"), "setlanguage32", this::setLanguage, PRIORITY_TOP, null, true); + finishMenu("/settings/language"); + + addMenuItem("/settings/deobfuscation", translate("menu.deobfuscation"), null, null, 0, null, false); + addToggleMenuItem("/settings/deobfuscation/old", translate("menu.file.deobfuscation.old"), "deobfuscation", "deobfuscateold16", (ActionEvent e) -> { + deobfuscationMode(e, 0); + }, 0); + addToggleMenuItem("/settings/deobfuscation/new", translate("menu.file.deobfuscation.new"), "deobfuscation", "deobfuscatenew16", (ActionEvent e) -> { + deobfuscationMode(e, 1); + }, 0); + + finishMenu("/settings/deobfuscation"); + + addMenuItem("/settings/advancedSettings", translate("menu.advancedsettings.advancedsettings"), null, null, 0, null, false); + addMenuItem("/settings/advancedSettings/advancedSettings", translate("menu.advancedsettings.advancedsettings"), "settings32", this::advancedSettings, PRIORITY_TOP, null, true); + addMenuItem("/settings/advancedSettings/clearRecentFiles", translate("menu.tools.otherTools.clearRecentFiles"), "clearrecent16", this::clearRecentFiles, PRIORITY_MEDIUM, null, true); + + finishMenu("/settings/advancedSettings"); + + finishMenu("/settings"); + + setMenuChecked("/settings/autodeobfuscation", Configuration.autoDeobfuscate.get()); + setMenuChecked("/settings/internalViewer", Configuration.internalFlashViewer.get() || externalFlashPlayerUnavailable); + setMenuChecked("/settings/parallelspeedup", Configuration.parallelSpeedUp.get()); + setMenuChecked("/settings/disableDecompilation", !Configuration.decompile.get()); + setMenuChecked("/settings/cacheOnDisk", !Configuration.cacheOnDisk.get()); + setMenuChecked("/settings/gotoMainClassOnStartup", Configuration.gotoMainClassOnStartup.get()); + setMenuChecked("/settings/autoRenameIdentifiers", Configuration.autoRenameIdentifiers.get()); + + if (externalFlashPlayerUnavailable) { + setMenuEnabled("/settings/internalViewer", false); + } + int deobfuscationMode = Configuration.deobfuscationMode.get(); + switch (deobfuscationMode) { + case 0: + setGroupSelection("deobfuscation", "/settings/deobfuscation/old"); + break; + case 1: + setGroupSelection("deobfuscation", "/settings/deobfuscation/new"); + break; + } + if (Platform.isWindows()) { + setMenuChecked("/settings/associate", ContextMenuTools.isAddedToContextMenu()); + + } + //Help + addMenuItem("/help", translate("menu.help"), null, null, 0, null, false); + addMenuItem("/help/about", translate("menu.help.about"), "about32", this::about, PRIORITY_TOP, null, true); + addMenuItem("/help/helpUs", translate("menu.help.helpus"), "donate32", this::helpUs, PRIORITY_TOP, null, true); + addMenuItem("/help/checkUpdates", translate("menu.help.checkupdates"), "update16", this::checkUpdates, PRIORITY_MEDIUM, null, true); + addMenuItem("/help/homepage", translate("menu.help.homepage"), "homepage16", this::homePage, PRIORITY_MEDIUM, null, true); + finishMenu("/help"); + + if (Configuration.showDebugMenu.get() || Configuration.debugMode.get()) { + + addMenuItem("/debug", "Debug", null, null, 0, null, false); + addMenuItem("/debug/removeNonScripts", "Remove non scripts", "update16", e -> removeNonScripts(), PRIORITY_MEDIUM, null, true); + addMenuItem("/debug/refreshDecompiled", "Refresh decompiled script", "update16", e -> refreshDecompiled(), PRIORITY_MEDIUM, null, true); + addMenuItem("/debug/checkResources", "Check resources", "update16", e -> checkResources(), PRIORITY_MEDIUM, null, true); + addMenuItem("/debug/callGc", "Call System.gc()", "update16", e -> System.gc(), PRIORITY_MEDIUM, null, true); + addMenuItem("/debug/emptyCache", "Empty cache", "update16", e -> { + SWF nswf = mainFrame.getPanel().getCurrentSwf(); + if (nswf != null) { + nswf.clearAllCache(); + } + }, PRIORITY_MEDIUM, null, true); + addMenuItem("/debug/memoryInformation", "Memory information", "update16", e -> { + String architecture = System.getProperty("sun.arch.data.model"); + Runtime runtime = Runtime.getRuntime(); + String info = "Architecture: " + architecture + Helper.newLine + + "Max: " + (runtime.maxMemory() / 1024 / 1024) + "MB" + Helper.newLine + + "Used: " + (runtime.totalMemory() / 1024 / 1024) + "MB" + Helper.newLine + + "Free: " + (runtime.freeMemory() / 1024 / 1024) + "MB"; + View.showMessageDialog(null, info); + SWF nswf = mainFrame.getPanel().getCurrentSwf(); + if (nswf != null) { + nswf.clearAllCache(); + } + }, PRIORITY_MEDIUM, null, true); + addMenuItem("/debug/fixAs3Code", "Fix AS3 code", "update16", e -> { + SWF nswf = mainFrame.getPanel().getCurrentSwf(); + if (nswf != null) { + nswf.fixAS3Code(); + } + }, PRIORITY_MEDIUM, null, true); + finishMenu("/debug"); + } + + finishMenu(""); + } + + private void viewModeResourcesButtonActionPerformed(ActionEvent evt) { + Configuration.dumpView.set(false); + mainFrame.getPanel().showView(MainPanel.VIEW_RESOURCES); + setGroupSelection("view", "/file/view/viewResources"); + setMenuChecked("/tools/timeline", false); + + } + + private void viewModeHexDumpButtonActionPerformed(ActionEvent evt) { + Configuration.dumpView.set(true); + mainFrame.getPanel().showView(MainPanel.VIEW_DUMP); + setGroupSelection("view", "/file/view/viewHex"); + setMenuChecked("/tools/timeline", false); + } + + private void debuggerSwitchButtonActionPerformed(ActionEvent evt) { + boolean debuggerOn = isMenuChecked("/tools/debugger/debuggerSwitch"); + if (!debuggerOn || View.showConfirmDialog((Component) mainFrame, translate("message.debugger"), translate("dialog.message.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE, Configuration.displayDebuggerInfo, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) { + switchDebugger(); + mainFrame.getPanel().refreshDecompiled(); + } else { + if (debuggerOn) { + setMenuChecked("/tools/debugger/debuggerSwitch", false); + } + } + setMenuEnabled("/tools/debugger/debuggerReplaceTrace", isMenuChecked("/tools/debugger/debuggerSwitch")); + } + + private void timelineButtonActionPerformed(ActionEvent evt) { + if (isMenuChecked("/tools/timeline")) { + if (!mainFrame.getPanel().showView(MainPanel.VIEW_TIMELINE)) { + setMenuChecked("/tools/timeline", false); + } else { + setGroupSelection("view", null); + } + } else { + if (Configuration.dumpView.get()) { + setGroupSelection("view", "/file/view/viewHex"); + mainFrame.getPanel().showView(MainPanel.VIEW_DUMP); + } else { + setGroupSelection("view", "/file/view/viewResources"); + mainFrame.getPanel().showView(MainPanel.VIEW_RESOURCES); + } + } + } + + protected void loadRecent(ActionEvent evt) { + List recentFiles = Configuration.getRecentFiles(); + clearMenu("/file/" + (supportsMenuAction() ? "open" : "recent")); + clearMenu("_/open"); + + for (int i = recentFiles.size() - 1; i >= 0; i--) { + final String f = recentFiles.get(i); + ActionListener a = (ActionEvent e) -> { + if (Main.openFile(f, null) == OpenFileResult.NOT_FOUND) { + if (View.showConfirmDialog(null, translate("message.confirm.recentFileNotFound"), translate("message.confirm"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_NO_OPTION) { + Configuration.removeRecentFile(f); + } + } + }; + addMenuItem("/file/" + (supportsMenuAction() ? "open" : "recent") + "/" + i, f, null, a, 0, null, true); + addMenuItem("_/open/" + i, f, null, a, 0, null, true); + } + + finishMenu("/file/" + (supportsMenuAction() ? "open" : "recent")); + finishMenu("_/open"); + + } + +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java index fc6665539..9fffebbda 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java @@ -62,6 +62,7 @@ public final class MainFrameRibbon extends AppRibbonFrame { boolean externalFlashPlayerUnavailable = flashPanel == null; mainMenu = new MainFrameRibbonMenu(this, ribbon, externalFlashPlayerUnavailable); + mainMenu.createMenuBar(); panel = new MainPanel(this, mainMenu, flashPanel); panel.setBackground(Color.yellow); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index 3e2a7cf8f..f84dccb68 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -16,29 +16,29 @@ */ package com.jpexs.decompiler.flash.gui; -import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.console.ContextMenuTools; -import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.helpers.Helper; -import com.jpexs.process.ProcessTools; -import com.sun.jna.Platform; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.swing.JCheckBox; +import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JToggleButton; import javax.swing.SwingUtilities; +import org.pushingpixels.flamingo.api.common.AbstractCommandButton; import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState; import org.pushingpixels.flamingo.api.common.CommandToggleButtonGroup; import org.pushingpixels.flamingo.api.common.JCommandButton; import org.pushingpixels.flamingo.api.common.JCommandButtonPanel; import org.pushingpixels.flamingo.api.common.JCommandToggleButton; -import org.pushingpixels.flamingo.api.common.icon.ResizableIcon; +import org.pushingpixels.flamingo.api.common.popup.JPopupPanel; +import org.pushingpixels.flamingo.api.common.popup.PopupPanelCallback; +import org.pushingpixels.flamingo.api.ribbon.AbstractRibbonBand; import org.pushingpixels.flamingo.api.ribbon.JRibbon; import org.pushingpixels.flamingo.api.ribbon.JRibbonBand; import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent; @@ -59,117 +59,11 @@ import org.pushingpixels.flamingo.internal.ui.ribbon.AbstractBandControlPanel; */ public class MainFrameRibbonMenu extends MainFrameMenu { - private final MainFrameRibbon mainFrame; - - private JCheckBox miAutoDeobfuscation; - - private JCheckBox miInternalViewer; - - private JCheckBox miParallelSpeedUp; - - private JCheckBox miAssociate; - - private JCheckBox miDecompile; - - private JCheckBox miCacheDisk; - - private JCheckBox miGotoMainClassOnStartup; - - private JCheckBox miAutoRenameIdentifiers; - - private JCommandButton saveCommandButton; - - private JCommandButton saveasCommandButton; - - private JCommandButton saveasexeCommandButton; - - private JCommandButton exportAllCommandButton; - - private JCommandButton exportFlaCommandButton; - - private JCommandButton exportSelectionCommandButton; - - private JCommandButton importTextCommandButton; - - private JCommandButton importScriptCommandButton; - - private JCommandButton importSymbolClassCommandButton; - - private JCommandButton importXmlCommandButton; - - private JCommandButton exportXmlCommandButton; - - private JCommandToggleButton viewModeResourcesToggleButton; - - private JCommandToggleButton viewModeHexToggleButton; - - private JCommandToggleButton deobfuscationModeOldToggleButton; - - private JCommandToggleButton deobfuscationModeNewToggleButton; - - private JCommandButton reloadCommandButton; - - private JCommandButton renameInvalidCommandButton; - - private JCommandButton globalRenameCommandButton; - - private JCommandButton deobfuscationCommandButton; - - private JCommandButton searchCommandButton; - - private JCommandButton replaceCommandButton; - - private JCommandToggleButton timeLineToggleButton; - - private CommandToggleButtonGroup timeLineToggleGroup; - - private JCommandButton gotoDocumentClassCommandButton; - - private JCommandButton clearRecentFilesCommandButton; - - private JCommandToggleButton debuggerSwitchCommandButton; - - private CommandToggleButtonGroup debuggerSwitchGroup; - - private JCommandButton debuggerReplaceTraceCommandButton; - - private JCommandButton debuggerLogCommandButton; - - private CommandToggleButtonGroup viewModeToggleGroup; - - RibbonApplicationMenuEntryPrimary exportFlaMenu; - - RibbonApplicationMenuEntryPrimary exportAllMenu; - - RibbonApplicationMenuEntryPrimary exportSelMenu; - - RibbonApplicationMenuEntryPrimary saveFileMenu; - - RibbonApplicationMenuEntryPrimary saveAsFileMenu; - - RibbonApplicationMenuEntryPrimary closeFileMenu; - - RibbonApplicationMenuEntryPrimary closeAllFilesMenu; + private JRibbon ribbon; public MainFrameRibbonMenu(MainFrameRibbon mainFrame, JRibbon ribbon, boolean externalFlashPlayerUnavailable) { - super(mainFrame); - this.mainFrame = mainFrame; - - ribbon.addTask(createFileRibbonTask()); - ribbon.addTask(createToolsRibbonTask()); - ribbon.addTask(createSettingsRibbonTask(externalFlashPlayerUnavailable)); - ribbon.addTask(createHelpRibbonTask()); - - if (Configuration.showDebugMenu.get() || Configuration.debugMode.get()) { - ribbon.addTask(createDebugRibbonTask()); - } - - ribbon.setApplicationMenu(createMainMenu()); - } - - @Override - public boolean isInternalFlashViewerSelected() { - return miInternalViewer.isSelected(); + super(mainFrame, externalFlashPlayerUnavailable); + this.ribbon = ribbon; } private String fixCommandTitle(String title) { @@ -181,76 +75,8 @@ public class MainFrameRibbonMenu extends MainFrameMenu { return title; } - private RibbonApplicationMenu createMainMenu() { - RibbonApplicationMenu mainMenu = new RibbonApplicationMenu(); - exportFlaMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("exportfla32"), translate("menu.file.export.fla"), this::exportFla, JCommandButton.CommandButtonKind.ACTION_ONLY); - exportAllMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("export32"), translate("menu.file.export.all"), this::exportAll, JCommandButton.CommandButtonKind.ACTION_ONLY); - exportSelMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("exportsel32"), translate("menu.file.export.selection"), this::exportSelected, JCommandButton.CommandButtonKind.ACTION_ONLY); - RibbonApplicationMenuEntryPrimary checkUpdatesMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("update32"), translate("menu.help.checkupdates"), this::checkUpdates, JCommandButton.CommandButtonKind.ACTION_ONLY); - RibbonApplicationMenuEntryPrimary aboutMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("about32"), translate("menu.help.about"), this::about, JCommandButton.CommandButtonKind.ACTION_ONLY); - RibbonApplicationMenuEntryPrimary openFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("open32"), translate("menu.file.open"), this::open, JCommandButton.CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION); - saveFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("save32"), translate("menu.file.save"), this::save, JCommandButton.CommandButtonKind.ACTION_ONLY); - saveAsFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("saveas32"), translate("menu.file.saveas"), this::saveAs, JCommandButton.CommandButtonKind.ACTION_ONLY); - closeFileMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("close32"), translate("menu.file.close"), this::close, JCommandButton.CommandButtonKind.ACTION_ONLY); - closeAllFilesMenu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon("close32"), translate("menu.file.closeAll"), this::closeAll, JCommandButton.CommandButtonKind.ACTION_ONLY); - 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(); - if (Main.openFile(source.fileName, null) == OpenFileResult.NOT_FOUND) { - if (View.showConfirmDialog(null, translate("message.confirm.recentFileNotFound"), translate("message.confirm"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_NO_OPTION) { - Configuration.removeRecentFile(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"), this::exit); - - mainMenu.addMenuEntry(openFileMenu); - mainMenu.addMenuEntry(saveFileMenu); - mainMenu.addMenuEntry(saveAsFileMenu); - mainMenu.addMenuEntry(closeFileMenu); - mainMenu.addMenuEntry(closeAllFilesMenu); - mainMenu.addMenuSeparator(); - mainMenu.addMenuEntry(exportFlaMenu); - mainMenu.addMenuEntry(exportAllMenu); - mainMenu.addMenuEntry(exportSelMenu); - mainMenu.addMenuSeparator(); - mainMenu.addMenuEntry(checkUpdatesMenu); - mainMenu.addMenuEntry(aboutMenu); - mainMenu.addFooterEntry(exitMenu); - mainMenu.addMenuSeparator(); - - return mainMenu; - } - - private List titleResizePolicies(final JRibbonBand ribbonBand) { - List resizePolicies = new ArrayList<>(); - resizePolicies.add(new BaseRibbonBandResizePolicy(ribbonBand.getControlPanel()) { + private RibbonBandResizePolicy titleResizePolicies(final JRibbonBand ribbonBand) { + return new BaseRibbonBandResizePolicy(ribbonBand.getControlPanel()) { @Override public int getPreferredWidth(int i, int i1) { return ribbonBand.getGraphics().getFontMetrics(ribbonBand.getFont()).stringWidth(ribbonBand.getTitle()) + 20; @@ -259,476 +85,463 @@ public class MainFrameRibbonMenu extends MainFrameMenu { @Override public void install(int i, int i1) { } - }); - return resizePolicies; + }; } private List getResizePolicies(JRibbonBand ribbonBand) { - List resizePolicies = new ArrayList<>(); - resizePolicies.add(new CoreRibbonResizePolicies.Mirror(ribbonBand.getControlPanel())); - resizePolicies.add(new IconRibbonBandResizePolicy(ribbonBand.getControlPanel())); - return resizePolicies; - } + final List myResizePolicies = new ArrayList<>(); + myResizePolicies.add(new CoreRibbonResizePolicies.Mirror(ribbonBand.getControlPanel())); + myResizePolicies.add(titleResizePolicies(ribbonBand)); + myResizePolicies.add(new IconRibbonBandResizePolicy(ribbonBand.getControlPanel())); - private List getIconBandResizePolicies(JRibbonBand ribbonBand) { List resizePolicies = new ArrayList<>(); - IconRibbonBandResizePolicy iconBandResizePolicy = new IconRibbonBandResizePolicy(ribbonBand.getControlPanel()); - final int width = Math.max(105, iconBandResizePolicy.getPreferredWidth(0, 0)); - resizePolicies.add(new BaseRibbonBandResizePolicy(ribbonBand.getControlPanel()) { + + resizePolicies.add(new RibbonBandResizePolicy() { + @Override public int getPreferredWidth(int i, int i1) { - return width; + int pw = 0; + for (RibbonBandResizePolicy p : myResizePolicies) { + int npw = p.getPreferredWidth(i, i1); + if (npw > pw) { + pw = npw; + } + } + return pw; } @Override public void install(int i, int i1) { + for (RibbonBandResizePolicy p : myResizePolicies) { + p.install(i, i1); + } } }); - resizePolicies.add(iconBandResizePolicy); return resizePolicies; } - private RibbonTask createFileRibbonTask() { - JRibbonBand editBand = new JRibbonBand(translate("menu.general"), null); - editBand.setResizePolicies(getResizePolicies(editBand)); - JCommandButton openCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.open")), View.getResizableIcon("open32")); - openCommandButton.addActionListener(this::open); - saveCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.save")), View.getResizableIcon("save32")); - saveCommandButton.addActionListener(this::save); - saveasCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.saveas")), View.getResizableIcon("saveas16")); - saveasCommandButton.addActionListener(this::saveAs); - - reloadCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.reload")), View.getResizableIcon("reload16")); - reloadCommandButton.addActionListener(this::reload); - - saveasexeCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.saveasexe")), View.getResizableIcon("saveasexe16")); - saveasexeCommandButton.addActionListener(this::saveAsExe);; - - editBand.addCommandButton(openCommandButton, RibbonElementPriority.TOP); - editBand.addCommandButton(saveCommandButton, RibbonElementPriority.TOP); - editBand.addCommandButton(saveasCommandButton, RibbonElementPriority.MEDIUM); - editBand.addCommandButton(saveasexeCommandButton, RibbonElementPriority.MEDIUM); - editBand.addCommandButton(reloadCommandButton, RibbonElementPriority.MEDIUM); - - JRibbonBand exportBand = new JRibbonBand(translate("menu.export"), null); - exportBand.setResizePolicies(getResizePolicies(exportBand)); - exportFlaCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.fla")), View.getResizableIcon("exportfla32")); - exportFlaCommandButton.addActionListener(this::exportFla); - exportAllCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.all")), View.getResizableIcon("export16")); - exportAllCommandButton.addActionListener(this::exportAll); - exportSelectionCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.selection")), View.getResizableIcon("exportsel16")); - exportSelectionCommandButton.addActionListener(this::exportSelected); - - exportXmlCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.export.xml")), View.getResizableIcon("exportxml32")); - exportXmlCommandButton.addActionListener(this::exportSwfXml); - - exportBand.addCommandButton(exportFlaCommandButton, RibbonElementPriority.TOP); - exportBand.addCommandButton(exportAllCommandButton, RibbonElementPriority.MEDIUM); - exportBand.addCommandButton(exportSelectionCommandButton, RibbonElementPriority.MEDIUM); - exportBand.addCommandButton(exportXmlCommandButton, RibbonElementPriority.MEDIUM); - - JRibbonBand importBand = new JRibbonBand(translate("menu.import"), null); - importBand.setResizePolicies(getResizePolicies(importBand)); - importTextCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.text")), View.getResizableIcon("importtext32")); - importTextCommandButton.addActionListener(this::importText); - - // todo: icon - importScriptCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.script")), View.getResizableIcon("importtext32")); - importScriptCommandButton.addActionListener(this::importScript); - - importSymbolClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.symbolClass")), View.getResizableIcon("importsymbolclass32")); - importSymbolClassCommandButton.addActionListener(this::importSymbolClass); - - importXmlCommandButton = new JCommandButton(fixCommandTitle(translate("menu.file.import.xml")), View.getResizableIcon("importxml32")); - importXmlCommandButton.addActionListener(this::importSwfXml); - - importBand.addCommandButton(importXmlCommandButton, RibbonElementPriority.TOP); - importBand.addCommandButton(importTextCommandButton, RibbonElementPriority.MEDIUM); - importBand.addCommandButton(importScriptCommandButton, RibbonElementPriority.MEDIUM); - importBand.addCommandButton(importSymbolClassCommandButton, RibbonElementPriority.MEDIUM); - - JRibbonBand viewBand = new JRibbonBand(translate("menu.view"), null); - viewBand.setResizePolicies(getResizePolicies(viewBand)); - - viewModeToggleGroup = new CommandToggleButtonGroup(); - - viewModeResourcesToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.file.view.resources")), View.getResizableIcon("viewresources16")); - viewModeResourcesToggleButton.addActionListener(this::viewModeResouresButtonActionPerformed); - - viewModeHexToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.file.view.hex")), View.getResizableIcon("viewhex16")); - viewModeHexToggleButton.addActionListener(this::viewModeHexDumpButtonActionPerformed); - - viewModeToggleGroup.add(viewModeResourcesToggleButton); - viewModeToggleGroup.add(viewModeHexToggleButton); - - if (Configuration.dumpView.get()) { - viewModeToggleGroup.setSelected(viewModeHexToggleButton, true); - } else { - viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, true); - } - - viewBand.addCommandButton(viewModeResourcesToggleButton, RibbonElementPriority.MEDIUM); - viewBand.addCommandButton(viewModeHexToggleButton, RibbonElementPriority.MEDIUM); - - return new RibbonTask(translate("menu.file"), editBand, exportBand, importBand, viewBand); - } - - private RibbonTask createToolsRibbonTask() { - - JRibbonBand debuggerBand = new JRibbonBand(translate("menu.debugger"), null); - debuggerBand.setResizePolicies(getResizePolicies(debuggerBand)); - - debuggerSwitchCommandButton = new JCommandToggleButton(translate("menu.debugger.switch"), View.getResizableIcon("debugger32")); - debuggerSwitchCommandButton.addActionListener(this::debuggerSwitchButtonActionPerformed); - - debuggerReplaceTraceCommandButton = new JCommandButton(translate("menu.debugger.replacetrace"), View.getResizableIcon("debuggerreplace16")); - debuggerReplaceTraceCommandButton.addActionListener(this::debuggerReplaceTraceCalls); - - debuggerLogCommandButton = new JCommandButton(translate("menu.debugger.showlog"), View.getResizableIcon("debuggerlog16")); - debuggerLogCommandButton.addActionListener(this::debuggerShowLog); - - debuggerSwitchGroup = new CommandToggleButtonGroup(); - debuggerSwitchGroup.add(debuggerSwitchCommandButton); - - debuggerSwitchCommandButton.setEnabled(false); - - debuggerReplaceTraceCommandButton.setEnabled(false); - - debuggerBand.addCommandButton(debuggerSwitchCommandButton, RibbonElementPriority.TOP); - debuggerBand.addCommandButton(debuggerReplaceTraceCommandButton, RibbonElementPriority.MEDIUM); - debuggerBand.addCommandButton(debuggerLogCommandButton, RibbonElementPriority.MEDIUM); - - // ----------------------------------------- TOOLS ----------------------------------- - JRibbonBand toolsBand = new JRibbonBand(translate("menu.tools"), null); - toolsBand.setResizePolicies(getResizePolicies(toolsBand)); - - searchCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.search")), View.getResizableIcon("search32")); - searchCommandButton.addActionListener((ActionEvent e) -> { - search(e, null); - }); - - replaceCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.replace")), View.getResizableIcon("replace32")); - replaceCommandButton.addActionListener(this::replace); - - timeLineToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.tools.timeline")), View.getResizableIcon("timeline32")); - timeLineToggleButton.addActionListener(this::timelineButtonActionPerformed); - - timeLineToggleGroup = new CommandToggleButtonGroup(); - timeLineToggleGroup.add(timeLineToggleButton); - - gotoDocumentClassCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.gotodocumentclass")), View.getResizableIcon("gotomainclass32")); - gotoDocumentClassCommandButton.addActionListener(this::gotoDucumentClass); - - JCommandButton proxyCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.proxy")), View.getResizableIcon("proxy16")); - proxyCommandButton.addActionListener(this::showProxy); - - JCommandButton loadMemoryCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchmemory")), View.getResizableIcon("loadmemory16")); - loadMemoryCommandButton.addActionListener(this::loadFromMemory); - - JCommandButton loadCacheCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.searchcache")), View.getResizableIcon("loadcache16")); - loadCacheCommandButton.addActionListener(this::loadFromCache); - - toolsBand.addCommandButton(searchCommandButton, RibbonElementPriority.TOP); - toolsBand.addCommandButton(replaceCommandButton, RibbonElementPriority.TOP); - toolsBand.addCommandButton(timeLineToggleButton, 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(getResizePolicies(deobfuscationBand)); - - deobfuscationCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.pcode")), View.getResizableIcon("deobfuscate32")); - deobfuscationCommandButton.addActionListener(this::deobfuscate); - globalRenameCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.globalrename")), View.getResizableIcon("rename16")); - globalRenameCommandButton.addActionListener(this::renameOneIdentifier); - renameInvalidCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.deobfuscation.renameinvalid")), View.getResizableIcon("renameall16")); - renameInvalidCommandButton.addActionListener(this::renameIdentifiers); - - deobfuscationBand.addCommandButton(deobfuscationCommandButton, RibbonElementPriority.TOP); - deobfuscationBand.addCommandButton(globalRenameCommandButton, RibbonElementPriority.MEDIUM); - deobfuscationBand.addCommandButton(renameInvalidCommandButton, RibbonElementPriority.MEDIUM); - - //JRibbonBand otherToolsBand = new JRibbonBand(translate("menu.tools.otherTools"), null); - //otherToolsBand.setResizePolicies(getResizePolicies(otherToolsBand)); - return new RibbonTask(translate("menu.tools"), toolsBand, deobfuscationBand, debuggerBand /*, otherToolsBand*/); - } - - private RibbonTask createSettingsRibbonTask(boolean externalFlashPlayerUnavailable) { - // ----------------------------------------- SETTINGS ----------------------------------- - - JRibbonBand settingsBand = new JRibbonBand(translate("menu.settings"), null); - settingsBand.setResizePolicies(getResizePolicies(settingsBand)); - - miAutoDeobfuscation = new JCheckBox(translate("menu.settings.autodeobfuscation")); - miAutoDeobfuscation.setSelected(Configuration.autoDeobfuscate.get()); - miAutoDeobfuscation.addActionListener(this::autoDeobfuscate); - - miInternalViewer = new JCheckBox(translate("menu.settings.internalflashviewer")); - miInternalViewer.setSelected(Configuration.internalFlashViewer.get() || externalFlashPlayerUnavailable); - if (externalFlashPlayerUnavailable) { - miInternalViewer.setEnabled(false); - } - miInternalViewer.addActionListener(this::internalViewerSwitch); - - miParallelSpeedUp = new JCheckBox(translate("menu.settings.parallelspeedup")); - miParallelSpeedUp.setSelected(Configuration.parallelSpeedUp.get()); - miParallelSpeedUp.addActionListener(this::parallelSpeedUp); - - miDecompile = new JCheckBox(translate("menu.settings.disabledecompilation")); - miDecompile.setSelected(!Configuration.decompile.get()); - miDecompile.addActionListener(this::disableDecompilation); - - miAssociate = new JCheckBox(translate("menu.settings.addtocontextmenu")); - miAssociate.addActionListener(this::associate); - miAssociate.setSelected(ContextMenuTools.isAddedToContextMenu()); - - miCacheDisk = new JCheckBox(translate("menu.settings.cacheOnDisk")); - miCacheDisk.setSelected(Configuration.cacheOnDisk.get()); - miCacheDisk.addActionListener(this::cacheOnDisk); - - miGotoMainClassOnStartup = new JCheckBox(translate("menu.settings.gotoMainClassOnStartup")); - miGotoMainClassOnStartup.setSelected(Configuration.gotoMainClassOnStartup.get()); - miGotoMainClassOnStartup.addActionListener(this::gotoDucumentClassOnStartup); - - miAutoRenameIdentifiers = new JCheckBox(translate("menu.settings.autoRenameIdentifiers")); - miAutoRenameIdentifiers.setSelected(Configuration.autoRenameIdentifiers.get()); - miAutoRenameIdentifiers.addActionListener(this::autoRenameIdentifiers); - - settingsBand.addRibbonComponent(new JRibbonComponent(miAutoDeobfuscation)); - settingsBand.addRibbonComponent(new JRibbonComponent(miInternalViewer)); - settingsBand.addRibbonComponent(new JRibbonComponent(miParallelSpeedUp)); - settingsBand.addRibbonComponent(new JRibbonComponent(miDecompile)); - if (Platform.isWindows()) { - settingsBand.addRibbonComponent(new JRibbonComponent(miAssociate)); - } - settingsBand.addRibbonComponent(new JRibbonComponent(miCacheDisk)); - settingsBand.addRibbonComponent(new JRibbonComponent(miGotoMainClassOnStartup)); - settingsBand.addRibbonComponent(new JRibbonComponent(miAutoRenameIdentifiers)); - - JRibbonBand languageBand = new JRibbonBand(translate("menu.language"), null); - List languageBandResizePolicies = getIconBandResizePolicies(languageBand); - languageBand.setResizePolicies(languageBandResizePolicies); - JCommandButton setLanguageCommandButton = new JCommandButton(fixCommandTitle(translate("menu.settings.language")), View.getResizableIcon("setlanguage32")); - setLanguageCommandButton.addActionListener(this::setLanguage); - languageBand.addCommandButton(setLanguageCommandButton, RibbonElementPriority.TOP); - - JRibbonBand advancedSettingsBand = new JRibbonBand(translate("menu.advancedsettings.advancedsettings"), null); - advancedSettingsBand.setResizePolicies(getResizePolicies(advancedSettingsBand)); - JCommandButton advancedSettingsCommandButton = new JCommandButton(fixCommandTitle(translate("menu.advancedsettings.advancedsettings")), View.getResizableIcon("settings32")); - advancedSettingsCommandButton.addActionListener(this::advancedSettings); - advancedSettingsBand.addCommandButton(advancedSettingsCommandButton, RibbonElementPriority.TOP); - - clearRecentFilesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.otherTools.clearRecentFiles")), View.getResizableIcon("clearrecent16")); - clearRecentFilesCommandButton.addActionListener(this::clearRecentFiles); - advancedSettingsBand.addCommandButton(clearRecentFilesCommandButton, RibbonElementPriority.MEDIUM); - - JRibbonBand deobfuscationBand = new JRibbonBand(translate("menu.deobfuscation"), null); - deobfuscationBand.setResizePolicies(titleResizePolicies(deobfuscationBand)); - - CommandToggleButtonGroup grpDeobfuscation = new CommandToggleButtonGroup(); - - deobfuscationModeOldToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.file.deobfuscation.old")), View.getResizableIcon("deobfuscateold16")); - deobfuscationModeOldToggleButton.addActionListener((ActionEvent e) -> { - deobfuscationMode(e, 0); - }); - - deobfuscationModeNewToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.file.deobfuscation.new")), View.getResizableIcon("deobfuscatenew16")); - deobfuscationModeNewToggleButton.addActionListener((ActionEvent e) -> { - deobfuscationMode(e, 1); - }); - - grpDeobfuscation.add(deobfuscationModeOldToggleButton); - grpDeobfuscation.add(deobfuscationModeNewToggleButton); - - int deobfuscationMode = Configuration.deobfuscationMode.get(); - switch (deobfuscationMode) { - case 0: - grpDeobfuscation.setSelected(deobfuscationModeOldToggleButton, true); - break; - case 1: - grpDeobfuscation.setSelected(deobfuscationModeNewToggleButton, true); - break; - } - - deobfuscationBand.addCommandButton(deobfuscationModeOldToggleButton, RibbonElementPriority.MEDIUM); - deobfuscationBand.addCommandButton(deobfuscationModeNewToggleButton, RibbonElementPriority.MEDIUM); - - return new RibbonTask(translate("menu.settings"), settingsBand, languageBand, advancedSettingsBand, deobfuscationBand); - } - - private RibbonTask createHelpRibbonTask() { - // ----------------------------------------- HELP ----------------------------------- - - JRibbonBand helpBand = new JRibbonBand(translate("menu.help"), null); - helpBand.setResizePolicies(getResizePolicies(helpBand)); - - JCommandButton checkForUpdatesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.checkupdates")), View.getResizableIcon("update16")); - checkForUpdatesCommandButton.addActionListener(this::checkUpdates); - JCommandButton helpUsUpdatesCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.helpus")), View.getResizableIcon("donate32")); - helpUsUpdatesCommandButton.addActionListener(this::helpUs); - JCommandButton homepageCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.homepage")), View.getResizableIcon("homepage16")); - homepageCommandButton.addActionListener(this::homePage); - JCommandButton aboutCommandButton = new JCommandButton(fixCommandTitle(translate("menu.help.about")), View.getResizableIcon("about32")); - aboutCommandButton.addActionListener(this::about); - - helpBand.addCommandButton(aboutCommandButton, RibbonElementPriority.TOP); - helpBand.addCommandButton(checkForUpdatesCommandButton, RibbonElementPriority.MEDIUM); - helpBand.addCommandButton(homepageCommandButton, RibbonElementPriority.MEDIUM); - helpBand.addCommandButton(helpUsUpdatesCommandButton, RibbonElementPriority.TOP); - return new RibbonTask(translate("menu.help"), helpBand); - } - - private RibbonTask createDebugRibbonTask() { - // ----------------------------------------- DEBUG ----------------------------------- - - ResizableIcon icon = View.getResizableIcon("update16"); - JRibbonBand debugBand = new JRibbonBand("Debug", null); - debugBand.setResizePolicies(getResizePolicies(debugBand)); - - JCommandButton removeNonScriptsCommandButton = new JCommandButton(fixCommandTitle("Remove non scripts"), icon); - removeNonScriptsCommandButton.addActionListener(e -> removeNonScripts()); - - JCommandButton refreshDecompiledCommandButton = new JCommandButton(fixCommandTitle("Refresh decompiled script"), icon); - refreshDecompiledCommandButton.addActionListener(e -> refreshDecompiled()); - - JCommandButton checkResourcesCommandButton = new JCommandButton(fixCommandTitle("Check resources"), icon); - checkResourcesCommandButton.addActionListener(e -> checkResources()); - - JCommandButton callGcCommandButton = new JCommandButton(fixCommandTitle("Call System.gc()"), icon); - callGcCommandButton.addActionListener(e -> System.gc()); - - JCommandButton emptyCacheCommandButton = new JCommandButton(fixCommandTitle("Empty cache"), icon); - emptyCacheCommandButton.addActionListener(e -> { - SWF swf = mainFrame.getPanel().getCurrentSwf(); - if (swf != null) { - swf.clearAllCache(); + private final Map menuItems = new HashMap<>(); + private final Map menuTitles = new HashMap<>(); + private final Map menuIcons = new HashMap<>(); + private final Map menuActions = new HashMap<>(); + private final Map menuLoaders = new HashMap<>(); + private final Map menuPriorities = new HashMap<>(); + + private final Map> menuSubs = new HashMap<>(); + private final Map menuType = new HashMap<>(); + private final Map menuGroup = new HashMap<>(); + + private final Map menuToggleGroups = new HashMap<>(); + private final Map menuToToggleGroup = new HashMap<>(); + + private static final int TYPE_MENU = 1; + private static final int TYPE_MENUITEM = 2; + private static final int TYPE_TOGGLEMENUITEM = 3; + + @Override + protected void loadRecent(ActionEvent evt) { + if (evt.getSource() instanceof JPanel) { + JPanel targetPanel = (JPanel) evt.getSource(); + 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(); + if (Main.openFile(source.fileName, null) == OpenFileResult.NOT_FOUND) { + if (View.showConfirmDialog(null, translate("message.confirm.recentFileNotFound"), translate("message.confirm"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_NO_OPTION) { + Configuration.removeRecentFile(source.fileName); + } + } + } + }); + j++; + historyButton.setHorizontalAlignment(SwingUtilities.LEFT); + openHistoryPanel.addButtonToLastGroup(historyButton); } - }); - - JCommandButton memoryInformationCommandButton = new JCommandButton(fixCommandTitle("Memory information"), icon); - memoryInformationCommandButton.addActionListener(e -> { - String architecture = System.getProperty("sun.arch.data.model"); - Runtime runtime = Runtime.getRuntime(); - String info = "Architecture: " + architecture + Helper.newLine - + "Max: " + (runtime.maxMemory() / 1024 / 1024) + "MB" + Helper.newLine - + "Used: " + (runtime.totalMemory() / 1024 / 1024) + "MB" + Helper.newLine - + "Free: " + (runtime.freeMemory() / 1024 / 1024) + "MB"; - View.showMessageDialog(null, info); - SWF swf = mainFrame.getPanel().getCurrentSwf(); - if (swf != null) { - swf.clearAllCache(); - } - }); - - JCommandButton fixAs3CodeCommandButton = new JCommandButton(fixCommandTitle("Fix AS3 code"), icon); - fixAs3CodeCommandButton.addActionListener(e -> { - SWF swf = mainFrame.getPanel().getCurrentSwf(); - if (swf != null) { - swf.fixAS3Code(); - } - }); - - debugBand.addCommandButton(removeNonScriptsCommandButton, RibbonElementPriority.MEDIUM); - debugBand.addCommandButton(refreshDecompiledCommandButton, RibbonElementPriority.MEDIUM); - debugBand.addCommandButton(checkResourcesCommandButton, RibbonElementPriority.MEDIUM); - debugBand.addCommandButton(callGcCommandButton, RibbonElementPriority.MEDIUM); - debugBand.addCommandButton(emptyCacheCommandButton, RibbonElementPriority.MEDIUM); - debugBand.addCommandButton(memoryInformationCommandButton, RibbonElementPriority.MEDIUM); - debugBand.addCommandButton(fixAs3CodeCommandButton, RibbonElementPriority.MEDIUM); - return new RibbonTask("Debug", debugBand); + openHistoryPanel.setMaxButtonColumns(1); + targetPanel.setLayout(new BorderLayout()); + targetPanel.add(openHistoryPanel, BorderLayout.CENTER); + } } @Override - public void updateComponents(SWF swf) { - super.updateComponents(swf); - boolean swfLoaded = swf != null; - List abcList = swfLoaded ? swf.getAbcList() : null; - boolean hasAbc = swfLoaded && abcList != null && !abcList.isEmpty(); - boolean hasDebugger = hasAbc && DebuggerTools.hasDebugger(swf); + public void finishMenu(String path) { + if (!menuTitles.containsKey(path)) { + throw new IllegalArgumentException("Menu not started: " + path); + } + boolean isAppMenu = path.equals("_"); + String title = menuTitles.get(path); + String icon = menuIcons.get(path); + ActionListener action = menuActions.get(path); + int priority = menuPriorities.get(path); + int type = menuType.get(path); + if (type != TYPE_MENU) { + throw new IllegalArgumentException("Not a menu: " + path); + } - exportAllMenu.setEnabled(swfLoaded); - exportFlaMenu.setEnabled(swfLoaded); - exportSelMenu.setEnabled(swfLoaded); - saveFileMenu.setEnabled(swfLoaded); - saveAsFileMenu.setEnabled(swfLoaded); - closeFileMenu.setEnabled(swfLoaded); - closeAllFilesMenu.setEnabled(swfLoaded); + String parts[] = path.contains("/") ? path.split("\\/") : new String[]{""}; + List subs = menuSubs.get(path); - boolean isBundle = swfLoaded && (swf.swfList != null) && (swf.swfList.isBundle()); - saveCommandButton.setEnabled(swfLoaded && ((!isBundle) || (!swf.swfList.bundle.isReadOnly()))); - saveasCommandButton.setEnabled(swfLoaded); - saveasexeCommandButton.setEnabled(swfLoaded); - exportAllCommandButton.setEnabled(swfLoaded); - exportFlaCommandButton.setEnabled(swfLoaded); - exportXmlCommandButton.setEnabled(swfLoaded); - exportSelectionCommandButton.setEnabled(swfLoaded); - importTextCommandButton.setEnabled(swfLoaded); - importScriptCommandButton.setEnabled(swfLoaded); - importSymbolClassCommandButton.setEnabled(swfLoaded); - importXmlCommandButton.setEnabled(swfLoaded); - reloadCommandButton.setEnabled(swfLoaded); - - renameInvalidCommandButton.setEnabled(swfLoaded); - globalRenameCommandButton.setEnabled(swfLoaded); - deobfuscationCommandButton.setEnabled(swfLoaded); - searchCommandButton.setEnabled(swfLoaded); - replaceCommandButton.setEnabled(swfLoaded); - timeLineToggleButton.setEnabled(swfLoaded); - - gotoDocumentClassCommandButton.setEnabled(hasAbc); - deobfuscationCommandButton.setEnabled(hasAbc); - debuggerSwitchCommandButton.setEnabled(hasAbc); - debuggerSwitchGroup.setSelected(debuggerSwitchCommandButton, hasDebugger); - debuggerReplaceTraceCommandButton.setEnabled(hasAbc && hasDebugger); - } - - private void debuggerSwitchButtonActionPerformed(ActionEvent evt) { - if (debuggerSwitchGroup.getSelected() == null || View.showConfirmDialog(mainFrame, translate("message.debugger"), translate("dialog.message.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE, Configuration.displayDebuggerInfo, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) { - switchDebugger(); - mainFrame.getPanel().refreshDecompiled(); - } else { - if (debuggerSwitchGroup.getSelected() == debuggerSwitchCommandButton) { - debuggerSwitchGroup.setSelected(debuggerSwitchCommandButton, false); + boolean onlyCheckboxes = true; + for (String sub : subs) { + if (sub.equals("-")) { + continue; + } + int subType = menuType.get(sub); + if (subType == TYPE_MENUITEM) { + onlyCheckboxes = false; + break; + } + String subIcon = menuIcons.get(sub); + if (subIcon != null) { + onlyCheckboxes = false; + break; } } - debuggerReplaceTraceCommandButton.setEnabled(debuggerSwitchGroup.getSelected() == debuggerSwitchCommandButton); - } + if (subs.isEmpty()) { + onlyCheckboxes = false; + } - private void viewModeResouresButtonActionPerformed(ActionEvent evt) { - Configuration.dumpView.set(false); - mainFrame.getPanel().showView(MainPanel.VIEW_RESOURCES); - timeLineToggleGroup.setSelected(timeLineToggleButton, false); - viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, true); - } + if (isAppMenu) { + RibbonApplicationMenu mainMenu = new RibbonApplicationMenu(); + for (String sub : subs) { + if (sub.equals("-")) { + mainMenu.addMenuSeparator(); + continue; + } - private void viewModeHexDumpButtonActionPerformed(ActionEvent evt) { - Configuration.dumpView.set(true); - mainFrame.getPanel().showView(MainPanel.VIEW_DUMP); - timeLineToggleGroup.setSelected(timeLineToggleButton, false); - viewModeToggleGroup.setSelected(viewModeHexToggleButton, true); - } + String subTitle = menuTitles.get(sub); + String subIcon = menuIcons.get(sub); + int subType = menuType.get(sub); + ActionListener subAction = menuActions.get(sub); + final ActionListener subLoader = menuLoaders.get(sub); + + if (sub.startsWith("_/$")) //FooterMenu + { + RibbonApplicationMenuEntryFooter footerMenu = new RibbonApplicationMenuEntryFooter(View.getResizableIcon(subIcon), subTitle, subAction); + mainMenu.addFooterEntry(footerMenu); + } else { + RibbonApplicationMenuEntryPrimary menu = new RibbonApplicationMenuEntryPrimary(View.getResizableIcon(subIcon), subTitle, subAction, + subType == TYPE_MENU ? JCommandButton.CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION : JCommandButton.CommandButtonKind.ACTION_ONLY); + + if (subLoader != null) { + menu.setRolloverCallback(new RibbonApplicationMenuEntryPrimary.PrimaryRolloverCallback() { + @Override + public void menuEntryActivated(JPanel targetPanel) { + subLoader.actionPerformed(new ActionEvent(targetPanel, 0, "load:" + sub)); + } + }); + } + mainMenu.addMenuEntry(menu); + } - private void timelineButtonActionPerformed(ActionEvent evt) { - timeLineToggleGroup.setSelected(timeLineToggleButton, timeLineToggleGroup.getSelected() == timeLineToggleButton); - if (timeLineToggleGroup.getSelected() == timeLineToggleButton) { - if (!mainFrame.getPanel().showView(MainPanel.VIEW_TIMELINE)) { - timeLineToggleGroup.setSelected(timeLineToggleButton, false); - } else { - viewModeToggleGroup.setSelected(viewModeHexToggleButton, false); - viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, false); } - } else { - if (Configuration.dumpView.get()) { - viewModeToggleGroup.setSelected(viewModeHexToggleButton, true); - mainFrame.getPanel().showView(MainPanel.VIEW_DUMP); - } else { - viewModeToggleGroup.setSelected(viewModeResourcesToggleButton, true); - mainFrame.getPanel().showView(MainPanel.VIEW_RESOURCES); + + ribbon.setApplicationMenu(mainMenu); + + } + + for (String sub : subs) { + if (sub.equals("-")) { + continue; + } + int subType = menuType.get(sub); + ActionListener subAction = menuActions.get(sub); + String subTitle = menuTitles.get(sub); + String subIcon = menuIcons.get(sub); + String subGroup = menuGroup.get(sub); + final ActionListener subLoader = menuLoaders.get(sub); + AbstractCommandButton but = null; + if (subType == TYPE_MENUITEM || (subType == TYPE_MENU && subAction != null)) { + JCommandButton cbut = null; + if (subIcon != null) { + cbut = new JCommandButton(fixCommandTitle(subTitle), View.getResizableIcon(subIcon)); + } else { + cbut = new JCommandButton(fixCommandTitle(subTitle)); + } + if (subLoader != null) { + cbut.setCommandButtonKind(JCommandButton.CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION); + cbut.setPopupCallback(new PopupPanelCallback() { + + @Override + public JPopupPanel getPopupPanel(JCommandButton jcb) { + JPopupPanel jp = new JPopupPanel() { + }; + + subLoader.actionPerformed(new ActionEvent(jp, 0, "load:" + sub)); + return jp; + } + }); + } + but = cbut; + } else if (subType == TYPE_TOGGLEMENUITEM) { + if (onlyCheckboxes) { + JCheckBox cb = new JCheckBox(subTitle); + if (subAction != null) { + cb.addActionListener(subAction); + } + menuItems.put(sub, cb); + } else { + if (subIcon != null) { + but = new JCommandToggleButton(fixCommandTitle(subTitle), View.getResizableIcon(subIcon)); + } else { + but = new JCommandToggleButton(fixCommandTitle(subTitle)); + } + menuToToggleGroup.get(sub).add((JCommandToggleButton) but); + } + } + if (but != null) { + if (subAction != null) { + but.addActionListener(subAction); + } + menuItems.put(sub, but); + } + } + + //if (parts.length == 3) + { //3rd level - it's a Band! + JRibbonBand band = new JRibbonBand(title, icon != null ? View.getResizableIcon(icon) : null, null); + band.setResizePolicies(getResizePolicies(band)); + int cnt = 0; + for (String sub : subs) { + if (sub.equals("-")) { + continue; + } + + Object o = menuItems.get(sub); + int subPriority = menuPriorities.get(sub); + int subType = menuType.get(sub); + ActionListener subAction = menuActions.get(sub); + if (subType != TYPE_MENU || (subAction != null)) { + if (o instanceof AbstractCommandButton) { + RibbonElementPriority ribbonPriority = RibbonElementPriority.MEDIUM; + switch (subPriority) { + case PRIORITY_LOW: + ribbonPriority = RibbonElementPriority.LOW; + break; + case PRIORITY_MEDIUM: + ribbonPriority = RibbonElementPriority.MEDIUM; + break; + case PRIORITY_TOP: + ribbonPriority = RibbonElementPriority.TOP; + break; + } + + band.addCommandButton((AbstractCommandButton) o, ribbonPriority); + cnt++; + } else if (o instanceof JComponent) { + band.addRibbonComponent(new JRibbonComponent((JComponent) o)); + cnt++; + } + } + } + if (cnt > 0) { + if (parts.length != 3) { + if (!menuSubs.containsKey(path)) { + menuSubs.put(path, new ArrayList<>()); + } + if (!menuSubs.get(path).contains(path + "/_")) { + menuSubs.get(path).add(0, path + "/_"); + } + menuItems.put(path + "/_", band); + + } else { + menuItems.put(path, band); + } + + } + + } + + if (parts.length == 1) { //1st level - it's ribbon + for (String sub : subs) { + if (sub.equals("-")) { + continue; + } + if (menuItems.get(sub) instanceof RibbonTask) { + ribbon.addTask((RibbonTask) menuItems.get(sub)); + } + } + } else if (parts.length == 2) { //2nd level - it's a Task! + int bandCount = 0; + for (String sub : subs) { + if (sub.equals("-")) { + continue; + } + + if (menuItems.get(sub) instanceof AbstractRibbonBand) { + bandCount++; + } + } + AbstractRibbonBand bands[] = new AbstractRibbonBand[bandCount]; + int b = 0; + for (String sub : subs) { + if (sub.equals("-")) { + continue; + } + if (menuItems.get(sub) instanceof AbstractRibbonBand) { + bands[b++] = (AbstractRibbonBand) menuItems.get(sub); + } + } + if (bands.length > 0) { + RibbonTask task = new RibbonTask(title, bands); + menuItems.put(path, task); } } } + + @Override + public void addMenuItem(String path, String title, String icon, ActionListener action, int priority, ActionListener subLoader, boolean isLeaf) { + String parentPath = path.contains("/") ? path.substring(0, path.lastIndexOf("/")) : ""; + if (!menuSubs.containsKey(parentPath)) { + throw new IllegalArgumentException("No parent menu exists: " + parentPath); + } + menuSubs.get(parentPath).add(path); + if (!isLeaf) { + menuSubs.put(path, new ArrayList<>()); + } + menuLoaders.put(path, subLoader); + menuTitles.put(path, title); + menuIcons.put(path, icon); + menuActions.put(path, action); + menuPriorities.put(path, priority); + menuType.put(path, isLeaf ? TYPE_MENUITEM : TYPE_MENU); + } + + @Override + public void addToggleMenuItem(String path, String title, String group, String icon, ActionListener action, int priority) { + addMenuItem(path, title, icon, action, priority, action, true); + menuType.put(path, TYPE_TOGGLEMENUITEM); + menuGroup.put(path, group); + if (group == null) { + group = path; + } + if (!menuToggleGroups.containsKey(group)) { + menuToggleGroups.put(group, new CommandToggleButtonGroup()); + } + menuToToggleGroup.put(path, menuToggleGroups.get(group)); + } + + @Override + public boolean isMenuChecked(String path) { + Object o = menuItems.get(path); + if (o instanceof JCommandToggleButton) { + JCommandToggleButton t = (JCommandToggleButton) o; + if (!menuToToggleGroup.containsKey(path)) { + throw new IllegalArgumentException("No toggle group for " + path); + } + return menuToToggleGroup.get(path).getSelected() == t; + } + if (o instanceof JCheckBox) { + return ((JCheckBox) o).isSelected(); + } + throw new IllegalArgumentException("Not a toggle menu"); + } + + @Override + public void setMenuChecked(String path, boolean checked) { + Object o = menuItems.get(path); + if (o instanceof JCommandToggleButton) { + JCommandToggleButton t = (JCommandToggleButton) o; + if (!menuToToggleGroup.containsKey(path)) { + throw new IllegalArgumentException("No toggle group for " + path); + } + menuToToggleGroup.get(path).setSelected(t, checked); + } else if (o instanceof JToggleButton) { + ((JToggleButton) o).setSelected(checked); + } else { + throw new IllegalArgumentException("Not a toggle menu"); + } + } + + @Override + public void setGroupSelection(String group, String selected) { + if (!menuToggleGroups.containsKey(group)) { + throw new IllegalArgumentException("Group " + group + " does not exist"); + } + menuToggleGroups.get(group).clearSelection(); + if (selected == null) { + return; + } + if (!menuItems.containsKey(selected)) { + throw new IllegalArgumentException("Selection " + selected + " not found"); + } + JCommandToggleButton c = (JCommandToggleButton) menuItems.get(selected); + menuToggleGroups.get(group).setSelected(c, true); + } + + @Override + public String getGroupSelection(String group) { + if (!menuToggleGroups.containsKey(group)) { + throw new IllegalArgumentException("Group " + group + " does not exist"); + } + JCommandToggleButton c = menuToggleGroups.get(group).getSelected(); + for (String path : menuItems.keySet()) { + if (menuItems.get(path) == c) { + return path; + } + } + return null; + } + + @Override + public void clearMenu(String path) { + + } + + @Override + public void setMenuEnabled(String path, boolean enabled) { + if (!menuItems.containsKey(path)) { + throw new IllegalArgumentException("Menu not found: " + path); + } + Object o = menuItems.get(path); + if (o instanceof JRibbonBand) { + ((JRibbonBand) o).setEnabled(enabled); + } else if (o instanceof AbstractCommandButton) { + ((AbstractCommandButton) o).setEnabled(enabled); + } else if (o instanceof JComponent) { + ((JComponent) o).setEnabled(enabled); + } else { + throw new IllegalArgumentException("Cannot set enabled to: " + path); + } + } + + @Override + public void initMenu() { + menuSubs.put("", new ArrayList<>()); + menuPriorities.put("", 0); + menuActions.put("", null); + menuTitles.put("", null); + menuIcons.put("", null); + menuType.put("", TYPE_MENU); + } + + @Override + public void addSeparator(String parentPath) { + if (!menuSubs.containsKey(parentPath)) { + throw new IllegalArgumentException("Menu does not exist: " + parentPath); + } + menuSubs.get(parentPath).add("-"); + } + + @Override + public boolean supportsMenuAction() { + return true; + } + + @Override + public boolean supportsAppMenu() { + return true; + } + } diff --git a/src/com/jpexs/decompiler/flash/gui/MenuBuilder.java b/src/com/jpexs/decompiler/flash/gui/MenuBuilder.java new file mode 100644 index 000000000..046a3c747 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/MenuBuilder.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import java.awt.event.ActionListener; + +/** + * Menu Builder. Creates menu. + * + * @author JPEXS + */ +public interface MenuBuilder { + + public static final int PRIORITY_LOW = 1; + public static final int PRIORITY_MEDIUM = 2; + public static final int PRIORITY_TOP = 3; + + /** + * Initializes menuBuilder + */ + public void initMenu(); + + /** + * Adds separator + * + * @param parentPath Parent menu path + */ + public void addSeparator(String parentPath); + + /** + * Adds menu item + * + * @param path Path + * @param title Title + * @param icon Icon - resource name + * @param action Action for clicking + * @param priority Priority + * @param subloader Action which loads menu inside + * @param isLeaf Has no subitems? + */ + public void addMenuItem(String path, String title, String icon, ActionListener action, int priority, ActionListener subloader, boolean isLeaf); + + /** + * Adds toggle item (radio/checkbox) + * + * @param path Path + * @param title Title + * @param group Group for toggling. Null = checkbox + * @param icon Icon - resource name + * @param action Action for clicking + * @param priority Priority + */ + public void addToggleMenuItem(String path, String title, String group, String icon, ActionListener action, int priority); + + /** + * Test menu checked (toggle) + * + * @param path Menu path + * @return True when checked + */ + public boolean isMenuChecked(String path); + + /** + * Sets menu checked (toggle) + * + * @param path Menu path + * @param checked Checked? + */ + public void setMenuChecked(String path, boolean checked); + + /** + * Sets checked item from group + * + * @param group Group name + * @param selected Selected path + */ + public void setGroupSelection(String group, String selected); + + /** + * Gets selected path from group + * + * @param group Group name + * @return Path + */ + public String getGroupSelection(String group); + + /** + * Clears menu + * + * @param path Path of menu + */ + public void clearMenu(String path); + + /** + * Sets enabled property of menu + * + * @param path Menu path + * @param enabled Enabled? + */ + public void setMenuEnabled(String path, boolean enabled); + + /** + * Finished creating menu + * + * @param path Menu path + */ + public void finishMenu(String path); + + /** + * Does this builder support actions for menus? (not menuitems) + * + * @return True if supports + */ + public boolean supportsMenuAction(); + + /** + * Does this builder support application menu (Path "_/...") + * + * @return True if supports + */ + public boolean supportsAppMenu(); + +}