From 854ed24b7c12c45ab61538686e1a2c3444192b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 18 Nov 2022 07:25:48 +0100 Subject: [PATCH] Added #1822, #1803 AS3 direct editation - optional using AIR (airglobal.swc) to compile --- CHANGELOG.md | 3 + .../parser/script/ActionScript3Parser.java | 22 ++++++-- .../flash/configuration/Configuration.java | 38 +++++++++++++ .../CustomConfigurationKeys.java | 1 + .../importers/As3ScriptReplacerFactory.java | 12 +++- .../importers/FFDecAs3ScriptReplacer.java | 20 ++++++- .../flash/ActionScript3DeobfuscatorTest.java | 2 +- .../console/CommandLineArgumentParser.java | 30 ++++++---- src/com/jpexs/decompiler/flash/gui/Main.java | 14 +++++ .../jpexs/decompiler/flash/gui/MainPanel.java | 17 ++++-- .../decompiler/flash/gui/abc/ABCPanel.java | 56 ++++++++++++++++--- .../locales/AdvancedSettingsDialog.properties | 2 + .../AdvancedSettingsDialog_cs.properties | 3 + .../flash/gui/locales/MainFrame.properties | 6 +- .../flash/gui/locales/MainFrame_cs.properties | 6 +- .../flash/gui/tagtree/TagTreeContextMenu.java | 2 +- 16 files changed, 195 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f9b15b3d..77c333425 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - [#1875] Remove no longer accessed items from cache after certain amount of time - [#1280] AS3 Direct editation of traits with the same name - [#1743] GFX - Adding DefineExternalImage2 and DefineSubImage tags +- [#1822], [#1803] AS3 direct editation - optional using AIR (airglobal.swc) to compile ### Fixed - [#1869] Replace references now replaces all references, not just PlaceObject @@ -2600,6 +2601,8 @@ All notable changes to this project will be documented in this file. [#1875]: https://www.free-decompiler.com/flash/issues/1875 [#1280]: https://www.free-decompiler.com/flash/issues/1280 [#1743]: https://www.free-decompiler.com/flash/issues/1743 +[#1822]: https://www.free-decompiler.com/flash/issues/1822 +[#1803]: https://www.free-decompiler.com/flash/issues/1803 [#1869]: https://www.free-decompiler.com/flash/issues/1869 [#1872]: https://www.free-decompiler.com/flash/issues/1872 [#1692]: https://www.free-decompiler.com/flash/issues/1692 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index d78bb0d64..dedc574d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -150,6 +150,8 @@ public class ActionScript3Parser { // private final AbcIndexing otherABCs; //private static final List playerABCs = new ArrayList<>(); private static AbcIndexing playerGlobalAbcIndex; + + private static AbcIndexing airGlobalAbcIndex; private long uniqId() { uniqLast++; @@ -2591,10 +2593,10 @@ public class ActionScript3Parser { addScriptFromTree(allOpenedNamespaces, traits, classPos); } - public ActionScript3Parser(ABC abc, List otherAbcs) throws IOException, InterruptedException { + public ActionScript3Parser(ABC abc, List otherAbcs, boolean air) throws IOException, InterruptedException { initPlayer(); - abcIndex = new AbcIndexing(playerGlobalAbcIndex); + abcIndex = new AbcIndexing(air ? airGlobalAbcIndex : playerGlobalAbcIndex); for (ABC a : otherAbcs) { abcIndex.addAbc(a); } @@ -2612,12 +2614,20 @@ public class ActionScript3Parser { SWF swf = new SWF(swc.getSWF("library.swf"), true); playerGlobalAbcIndex = new AbcIndexing(swf); } + if (airGlobalAbcIndex == null) { + if (Configuration.getAirSWC() == null) { + return; + } + SWC swc = new SWC(new FileInputStream(Configuration.getAirSWC())); + SWF swf = new SWF(swc.getSWF("library.swf"), true); + airGlobalAbcIndex = new AbcIndexing(swf); + } } - public static void compile(String src, ABC abc, List otherABCs, String fileName, int classPos, int scriptIndex) throws AVM2ParseException, IOException, InterruptedException, CompilationException { + public static void compile(String src, ABC abc, List otherABCs, String fileName, int classPos, int scriptIndex, boolean air) throws AVM2ParseException, IOException, InterruptedException, CompilationException { //List parABCs = new ArrayList<>(); initPlayer(); - ActionScript3Parser parser = new ActionScript3Parser(abc, otherABCs); + ActionScript3Parser parser = new ActionScript3Parser(abc, otherABCs, air); boolean success = false; ABC originalAbc = ((ABCContainerTag) ((Tag) abc.parentTag).cloneTag()).getABC(); try { @@ -2638,12 +2648,12 @@ public class ActionScript3Parser { } } - public static void compile(SWF swf, String src, String dst, int classPos, int scriptIndex) { + public static void compile(SWF swf, String src, String dst, int classPos, int scriptIndex, boolean air) { System.err.println("WARNING: AS3 compiler is not finished yet. This is only used for debuggging!"); try { initPlayer(); ABC abc = new ABC(null); - ActionScript3Parser parser = new ActionScript3Parser(abc, new ArrayList<>()); + ActionScript3Parser parser = new ActionScript3Parser(abc, new ArrayList<>(), air); parser.addScript(new String(Helper.readFile(src), Utf8Helper.charset), src, classPos, scriptIndex); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File(dst)))) { abc.saveToStream(fos); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index da85fb31d..61c539128 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.helpers.CodeFormatting; import com.jpexs.decompiler.flash.helpers.FontHelper; import com.jpexs.decompiler.flash.importers.TextImportResizeTextBoundsMode; import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Path; import java.awt.Font; import java.io.BufferedOutputStream; import java.io.File; @@ -791,6 +792,11 @@ public final class Configuration { @ConfigurationDefaultInt(5 * 60 * 1000) @ConfigurationCategory("limit") public static ConfigurationItem maxCachedTime = null; + + @ConfigurationDefaultString("") + @ConfigurationCategory("paths") + @ConfigurationFile(".*\\.swc$") + public static ConfigurationItem airLibLocation = null; private enum OSId { WINDOWS, OSX, UNIX @@ -1071,6 +1077,12 @@ public final class Configuration { playerLibLocation.set(swcFile.getAbsolutePath()); } } + if (airLibLocation.get("").isEmpty()) { + File swcFile = getAirSwcOld(); + if (swcFile != null) { + airLibLocation.set(swcFile.getAbsolutePath()); + } + } } public static Object getDefaultValue(Field field) { @@ -1211,7 +1223,33 @@ public final class Configuration { } return ret; } + + public static File getAirSWC() { + String libLocation = airLibLocation.get(""); + File ret = null; + if (!libLocation.isEmpty()) { + ret = new File(libLocation); + } + if (ret == null || !ret.exists()) { + ret = getAirSwcOld(); + if (ret != null) { + airLibLocation.set(ret.getAbsolutePath()); + } + } + return ret; + } + private static File getAirSwcOld() { + File libsDir = getFlashLibPath(); + if (libsDir != null && libsDir.exists()) { + File airFile = new File(Path.combine(libsDir.getAbsolutePath(), "airglobal.swc")); + if (airFile.exists()) { + return airFile; + } + } + return null; + } + private static File getPlayerSwcOld() { File libsDir = getFlashLibPath(); if (libsDir != null && libsDir.exists()) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java index 1e214f87b..ad454f502 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java @@ -8,4 +8,5 @@ public class CustomConfigurationKeys { public static final String KEY_LAST_SELECTED_PATH_RESOURCES = "lastSelectedPath.resources"; public static final String KEY_LAST_SELECTED_PATH_TAGLIST = "lastSelectedPath.taglist"; public static final String KEY_CHARSET = "charset"; + public static final String KEY_LIBRARY = "library"; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java index c1eed307c..c4430a9f3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplacerFactory.java @@ -21,8 +21,10 @@ import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer; public class As3ScriptReplacerFactory { - public static As3ScriptReplacerInterface createByConfig() { - if (Configuration.useFlexAs3Compiler.get()) { + public static As3ScriptReplacerInterface createByConfig(boolean air) { + if (air) { + return createFFDecAir(); + } else if (Configuration.useFlexAs3Compiler.get()) { return createFlex(); } else { return createFFDec(); @@ -34,6 +36,10 @@ public class As3ScriptReplacerFactory { } public static As3ScriptReplacerInterface createFFDec() { - return new FFDecAs3ScriptReplacer(); + return new FFDecAs3ScriptReplacer(false); + } + + public static As3ScriptReplacerInterface createFFDecAir() { + return new FFDecAs3ScriptReplacer(true); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java index 01eb1b665..f1c1becc0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java @@ -33,6 +33,14 @@ import java.util.List; public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface { + private boolean air; + + public FFDecAs3ScriptReplacer(boolean air) { + this.air = air; + } + + + @Override public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException { ABC abc = pack.abc; @@ -63,7 +71,7 @@ public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface { otherAbcs.remove(abc); abc.script_info.get(oldIndex).delete(abc, true); - ActionScript3Parser.compile(text, abc, otherAbcs, scriptName, newClassIndex, oldIndex); + ActionScript3Parser.compile(text, abc, otherAbcs, scriptName, newClassIndex, oldIndex, air); if (pack.isSimple) { // Move newly added script to its position abc.script_info.set(oldIndex, abc.script_info.get(newIndex)); @@ -84,11 +92,17 @@ public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface { } @Override - public boolean isAvailable() { - File swc = Configuration.getPlayerSWC(); + public boolean isAvailable() { + File swc = air ? Configuration.getAirSWC() : Configuration.getPlayerSWC(); return !(swc == null || !swc.exists()); } + public boolean isAir() { + return air; + } + + + @Override public void initReplacement(ScriptPack pack) { //empty diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java index 8414cdd8b..defb3f9ab 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -119,7 +119,7 @@ public class ActionScript3DeobfuscatorTest extends ActionScriptTestBase { return 0; } }); - ActionScript3Parser par = new ActionScript3Parser(abc, new ArrayList<>()); + ActionScript3Parser par = new ActionScript3Parser(abc, new ArrayList<>(), false); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); par.addScript(str, "Test.as", 0, 0); diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index cc2c4c1ab..efdaaae30 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -672,6 +672,12 @@ public class CommandLineArgumentParser { out.println(" ...sets desired character set for reading/writing SWF files with SWF version <= 5"); out.println(" (use in combination with other commands)"); } + + if (filter == null || filter.equals("air")) { + out.println(" " + (cnt++) + ") -air"); + out.println(" ...use AIR (airglobal.swc) for AS3 compilation instead of playerglobal.swc"); + out.println(" (use in combination with other commands)"); + } printCmdLineUsageExamples(out, filter); @@ -800,10 +806,11 @@ public class CommandLineArgumentParser { double zoom = 1; String charset = Charset.defaultCharset().name(); boolean cliMode = false; + boolean air = false; Selection selection = new Selection(); Selection selectionIds = new Selection(); List selectionClasses = null; - String nextParam = null, nextParamOriginal = null; + String nextParam = null, nextParamOriginal = null; OUTER: while (true) { nextParamOriginal = args.pop(); @@ -814,6 +821,9 @@ public class CommandLineArgumentParser { nextParam = ""; } switch (nextParam) { + case "-air": + air = true; + break; case "-cli": cliMode = true; break; @@ -955,7 +965,7 @@ public class CommandLineArgumentParser { } else if (command.equals("flashpaper2pdf")) { parseFlashPaperToPdf(selection, zoom, args, charset); } else if (command.equals("replace")) { - parseReplace(args, charset); + parseReplace(args, charset, air); } else if (command.equals("replacealpha")) { parseReplaceAlpha(args, charset); } else if (command.equals("replacecharacter")) { @@ -973,9 +983,9 @@ public class CommandLineArgumentParser { } else if (command.equals("doc")) { parseDoc(args); } else if (command.equals("importscript")) { - parseImportScript(args, charset); + parseImportScript(args, charset, air); } else if (command.equals("as3compiler")) { - ActionScript3Parser.compile(null /*?*/, args.pop(), args.pop(), 0, 0); + ActionScript3Parser.compile(null /*?*/, args.pop(), args.pop(), 0, 0, air); } else if (nextParam.equals("--debugtool")) { parseDebugTool(args, charset); } else if (nextParam.equals("--compareresources")) { @@ -2979,7 +2989,7 @@ public class CommandLineArgumentParser { System.exit(0); } - private static void parseReplace(Stack args, String charset) { + private static void parseReplace(Stack args, String charset, boolean air) { if (args.size() < 3) { badArguments("replace"); } @@ -3110,7 +3120,7 @@ public class CommandLineArgumentParser { String repText = Helper.readTextFile(repFile); ScriptPack pack = entry; if (Path.getExtension(repFile).equals(".as")) { - replaceAS3(repFile, repText, pack); + replaceAS3(repFile, repText, pack, air); } else { // todo: get traits if (args.isEmpty()) { @@ -3593,7 +3603,7 @@ public class CommandLineArgumentParser { } } - private static void parseImportScript(Stack args, String charset) { + private static void parseImportScript(Stack args, String charset, boolean air) { String flexLocation = Configuration.flexSdkLocation.get(); if (Configuration.useFlexAs3Compiler.get() && (flexLocation.isEmpty() || (!new File(flexLocation).exists()))) { @@ -3612,7 +3622,7 @@ public class CommandLineArgumentParser { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get(), charset); String scriptsFolder = Path.combine(args.pop(), ScriptExportSettings.EXPORT_FOLDER_NAME); new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true)); - new AS3ScriptImporter().importScripts(As3ScriptReplacerFactory.createByConfig(), scriptsFolder, swf.getAS3Packs()); + new AS3ScriptImporter().importScripts(As3ScriptReplacerFactory.createByConfig(air), scriptsFolder, swf.getAS3Packs()); try { try ( OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { @@ -3742,10 +3752,10 @@ public class CommandLineArgumentParser { ((Tag) abc.parentTag).setModified(true); } - private static void replaceAS3(String asp, String as, ScriptPack pack) throws IOException, InterruptedException { + private static void replaceAS3(String asp, String as, ScriptPack pack, boolean air) throws IOException, InterruptedException { System.out.println("Replacing: " + asp); System.out.println("Warning: This feature is EXPERIMENTAL"); - As3ScriptReplacerInterface scriptReplacer = As3ScriptReplacerFactory.createByConfig(); + As3ScriptReplacerInterface scriptReplacer = As3ScriptReplacerFactory.createByConfig(air); if (!scriptReplacer.isAvailable()) { System.err.println("Current script replacer is not available."); if (scriptReplacer instanceof FFDecAs3ScriptReplacer) { diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 95fd04874..349b48a4a 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -202,7 +202,21 @@ public class Main { public static CancellableWorker importWorker = null; public static CancellableWorker deobfuscatePCodeWorker = null; public static CancellableWorker swfPrepareWorker = null; + + public static final int LIBRARY_AIR = 0; + public static final int LIBRARY_FLASH = 1; + + public static boolean isSwfAir(SWF swf) { + SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + if (conf != null) { + String libraryAsStr = conf.getCustomData(CustomConfigurationKeys.KEY_LIBRARY, "" + LIBRARY_FLASH); + int libraryAsInt = Integer.parseInt(libraryAsStr); + return libraryAsInt == LIBRARY_AIR; + } + return false; + } + //This method makes file watcher to shut up during our own file saving public static void startSaving(File savedFile) { savedFiles.add(savedFile); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 002618f51..517d64311 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2947,16 +2947,23 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } - public As3ScriptReplacerInterface getAs3ScriptReplacer() { - As3ScriptReplacerInterface r = As3ScriptReplacerFactory.createByConfig(); + public As3ScriptReplacerInterface getAs3ScriptReplacer(boolean air) { + As3ScriptReplacerInterface r = As3ScriptReplacerFactory.createByConfig(air); if (!r.isAvailable()) { if (r instanceof MxmlcAs3ScriptReplacer) { if (ViewMessages.showConfirmDialog(this, AppStrings.translate("message.flexpath.notset"), AppStrings.translate("error"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) { Main.advancedSettings("paths"); } } else if (r instanceof FFDecAs3ScriptReplacer) { - if (ViewMessages.showConfirmDialog(this, AppStrings.translate("message.playerpath.lib.notset"), AppStrings.translate("message.action.playerglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) { - Main.advancedSettings("paths"); + FFDecAs3ScriptReplacer fr = (FFDecAs3ScriptReplacer) r; + if (fr.isAir()) { + if (ViewMessages.showConfirmDialog(this, AppStrings.translate("message.airpath.lib.notset"), AppStrings.translate("message.action.airglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) { + Main.advancedSettings("paths"); + } + } else { + if (ViewMessages.showConfirmDialog(this, AppStrings.translate("message.playerpath.lib.notset"), AppStrings.translate("message.action.playerglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) { + Main.advancedSettings("paths"); + } } } else { //Not translated yet - just in case there are more Script replacers in the future. Unused now. @@ -2968,7 +2975,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } public void importScript(final SWF swf) { - As3ScriptReplacerInterface as3ScriptReplacer = getAs3ScriptReplacer(); + As3ScriptReplacerInterface as3ScriptReplacer = getAs3ScriptReplacer(Main.isSwfAir(swf)); if (as3ScriptReplacer == null) { return; } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index ae4740da6..dbd0d9a0e 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -45,6 +45,8 @@ import com.jpexs.decompiler.flash.action.parser.script.ActionScriptLexer; import com.jpexs.decompiler.flash.action.parser.script.ParsedSymbol; import com.jpexs.decompiler.flash.action.parser.script.SymbolType; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.CustomConfigurationKeys; +import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration; import com.jpexs.decompiler.flash.ecma.EcmaScript; import com.jpexs.decompiler.flash.gui.AppDialog; import com.jpexs.decompiler.flash.gui.AppStrings; @@ -156,6 +158,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener libraryComboBox; + public final DecompiledEditorPane decompiledTextArea; public final JScrollPane decompiledScrollPane; @@ -225,12 +231,17 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener(); + libraryComboBox.addItem("AIR (airglobal.swc)"); + libraryComboBox.addItem("Flash (playerglobal.swc)"); + libraryComboBox.setSelectedIndex(Main.LIBRARY_FLASH); + libraryComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + SWF swf = getSwf(); + if (swf == null) { + return; + } + SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + conf.setCustomData(CustomConfigurationKeys.KEY_LIBRARY, "" + libraryComboBox.getSelectedIndex()); + } + }); + + librarySelectPanel.add(new JLabel(AppStrings.translate("library"))); + librarySelectPanel.add(libraryComboBox); + toolbarPanel.add(librarySelectPanel, BorderLayout.EAST); + + toolbarPanel.setAlignmentX(0); + + iconDecPanel.add(toolbarPanel); JPanel panelWithHint = new JPanel(new BorderLayout()); panelWithHint.setAlignmentX(0); @@ -1436,13 +1475,14 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener