private void resetButtonActionPerformed(ActionEvent evt) {
   Map<String, Field> rfields = Configuration.getConfigurationFields();
   for (Entry<String, Field> entry : rfields.entrySet()) {
     String name = entry.getKey();
     Field field = entry.getValue();
     try {
       ConfigurationItem item = (ConfigurationItem) field.get(null);
       item.unset();
     } catch (IllegalArgumentException | IllegalAccessException ex) {
       // Reflection exceptions. This should never happen
       throw new Error(ex.getMessage());
     }
   }
   Configuration.saveConfig();
   setVisible(false);
   showRestartConfirmDialod();
 }
  private void editDecompiledButtonActionPerformed(ActionEvent evt) {
    File swc = Configuration.getPlayerSWC();
    final String adobePage = "http://www.adobe.com/support/flashplayer/downloads.html";
    if (swc == null) {
      if (View.showConfirmDialog(
              this,
              AppStrings.translate("message.action.playerglobal.needed")
                  .replace("%adobehomepage%", adobePage),
              AppStrings.translate("message.action.playerglobal.title"),
              JOptionPane.OK_CANCEL_OPTION,
              JOptionPane.INFORMATION_MESSAGE)
          == JOptionPane.OK_OPTION) {

        View.navigateUrl(adobePage);

        int ret;
        do {
          ret =
              View.showConfirmDialog(
                  this,
                  AppStrings.translate("message.action.playerglobal.place")
                      .replace("%libpath%", Configuration.getFlashLibPath().getAbsolutePath()),
                  AppStrings.translate("message.action.playerglobal.title"),
                  JOptionPane.OK_CANCEL_OPTION,
                  JOptionPane.INFORMATION_MESSAGE);
          swc = Configuration.getPlayerSWC();
        } while (ret == JOptionPane.OK_OPTION && swc == null);
      }
    }
    if (swc != null) {
      if (View.showConfirmDialog(
              null,
              AppStrings.translate("message.confirm.experimental.function"),
              AppStrings.translate("message.warning"),
              JOptionPane.OK_CANCEL_OPTION,
              JOptionPane.WARNING_MESSAGE,
              Configuration.warningExperimentalAS3Edit,
              JOptionPane.OK_OPTION)
          == JOptionPane.OK_OPTION) {
        setDecompiledEditMode(true);
      }
    }
  }
 private synchronized void savePair() {
   if (!allowSave) {
     return;
   }
   TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
   if (item instanceof FontTag) {
     FontTag f = (FontTag) item;
     SWF swf = f.getSwf();
     String selectedName =
         ((FontFace) fontFaceSelection.getSelectedItem()).font.getFontName(Locale.ENGLISH);
     swf.sourceFontNamesMap.put(f.getFontId(), selectedName);
     Configuration.addFontPair(
         swf.getShortFileName(), f.getFontId(), f.getFontNameIntag(), selectedName);
   }
 }
  @Test(dataProvider = "provideFiles")
  public void testDirectEditing(String filePath)
      throws IOException, InterruptedException, AVM2ParseException, CompilationException {
    File playerSWC = Configuration.getPlayerSWC();
    if (playerSWC == null) {
      throw new IOException(
          "Player SWC library not found, please place it to " + Configuration.getFlashLibPath());
    }
    try {
      SWF swf = new SWF(new BufferedInputStream(new FileInputStream(filePath)), false);
      if (swf.isAS3()) {
        boolean dotest = false;
        List<ABC> allAbcs = new ArrayList<>();
        for (ABCContainerTag ct : swf.getAbcList()) {
          allAbcs.add(ct.getABC());
        }
        for (ABC abc : allAbcs) {
          for (int s = 0; s < abc.script_info.size(); s++) {
            String startAfter = null;
            HighlightedTextWriter htw = new HighlightedTextWriter(new CodeFormatting(), false);
            ScriptPack en = abc.script_info.get(s).getPacks(abc, s, null, allAbcs).get(0);
            String classPathString = en.getClassPath().toString();
            if (startAfter == null || classPathString.equals(startAfter)) {
              dotest = true;
            }
            if (!dotest) {
              System.out.println("Skipped:" + classPathString);
              continue;
            }

            System.out.println("Recompiling:" + classPathString + "...");
            en.toSource(htw, abc.script_info.get(s).traits.traits, ScriptExportMode.AS, false);
            String original = htw.toString();
            com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser.compile(
                original,
                abc,
                allAbcs,
                false,
                en.getClassPath().className + ".as",
                abc.instance_info.size());

            // remove last compiled script:
            abc.script_info.remove(abc.script_info.size() - 1);
          }
        }
      } else {
        Map<String, ASMSource> asms = swf.getASMs(false);

        for (ASMSource asm : asms.values()) {
          try {
            HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false);
            Action.actionsToSource(asm, asm.getActions(), asm.toString() /*FIXME?*/, writer);
            String as = writer.toString();
            as = asm.removePrefixAndSuffix(as);
            ActionScriptParser par = new ActionScriptParser(swf.version);
            try {
              asm.setActions(par.actionsFromString(as));
            } catch (ActionParseException | CompilationException ex) {
              fail("Unable to parse: " + as + "/" + asm.toString(), ex);
            }
            writer = new HighlightedTextWriter(new CodeFormatting(), false);
            Action.actionsToSource(asm, asm.getActions(), asm.toString() /*FIXME?*/, writer);
            String as2 = writer.toString();
            as2 = asm.removePrefixAndSuffix(as2);
            try {
              asm.setActions(par.actionsFromString(as2));
            } catch (ActionParseException | CompilationException ex) {
              fail(
                  "Unable to parse: " + asm.getSwf().getShortFileName() + "/" + asm.toString(), ex);
            }
            writer = new HighlightedTextWriter(new CodeFormatting(), false);
            Action.actionsToSource(asm, asm.getActions(), asm.toString() /*FIXME?*/, writer);
            String as3 = writer.toString();
            as3 = asm.removePrefixAndSuffix(as3);
            if (!as3.equals(as2)) {
              fail(
                  "ActionScript is different: "
                      + asm.getSwf().getShortFileName()
                      + "/"
                      + asm.toString());
            }
          } catch (InterruptedException
              | IOException
              | OutOfMemoryError
              | TranslateException
              | StackOverflowError ex) {
          }
        }
      }
    } catch (Exception ex) {
      fail("Exception during decompilation: " + filePath, ex);
    }
  }
  @SuppressWarnings("unchecked")
  private void okButtonActionPerformed(ActionEvent evt) {
    boolean modified = false;
    Map<String, Field> fields = Configuration.getConfigurationFields();
    Map<String, Object> values = new HashMap<>();
    for (String name : fields.keySet()) {
      Component c = componentsMap.get(name);
      Object value = null;

      ParameterizedType listType = (ParameterizedType) fields.get(name).getGenericType();
      java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0];
      if (!(itemType2 instanceof Class<?>)) {
        continue;
      }

      Class itemType = (Class<?>) itemType2;
      if (name.equals("gui.skin")) {
        value = ((SkinSelect) ((JComboBox<SkinSelect>) c).getSelectedItem()).className;
      } else if (itemType == String.class) {
        value = ((JTextField) c).getText();
      }
      if (itemType == Boolean.class) {
        value = ((JCheckBox) c).isSelected();
      }

      if (itemType == Calendar.class) {
        Calendar cal = Calendar.getInstance();
        try {
          cal.setTime(new SimpleDateFormat().parse(((JTextField) c).getText()));
        } catch (ParseException ex) {
          c.requestFocusInWindow();
          return;
        }
        value = cal;
      }

      if (itemType.isEnum()) {
        String stringValue = (String) ((JComboBox<String>) c).getSelectedItem();
        value = Enum.valueOf(itemType, stringValue);
      }

      try {
        if (itemType == Integer.class) {
          value = Integer.parseInt(((JTextField) c).getText());
        }
        if (itemType == Long.class) {
          value = Long.parseLong(((JTextField) c).getText());
        }
        if (itemType == Double.class) {
          value = Double.parseDouble(((JTextField) c).getText());
        }
        if (itemType == Float.class) {
          value = Float.parseFloat(((JTextField) c).getText());
        }
      } catch (NumberFormatException nfe) {
        if (!((JTextField) c).getText().isEmpty()) {
          c.requestFocusInWindow();
          return;
        } // else null
      }
      values.put(name, value);
    }

    for (String name : fields.keySet()) {
      Component c = componentsMap.get(name);
      Object value = values.get(name);

      Field field = fields.get(name);
      ConfigurationItem item = null;
      try {
        item = (ConfigurationItem) field.get(null);
      } catch (IllegalArgumentException | IllegalAccessException ex) {
        // Reflection exceptions. This should never happen
        throw new Error(ex.getMessage());
      }
      if (item.get() == null || !item.get().equals(value)) {
        if (item.hasValue() || value != null) {
          item.set(value);
          modified = true;
        }
      }
    }
    Configuration.saveConfig();
    setVisible(false);
    if (modified) {
      showRestartConfirmDialod();
    }
  }
  public static void getCategories(
      Map<String, Component> componentsMap,
      Map<String, Component> tabs,
      JComboBox<?> skinComboBox,
      ResourceBundle resourceBundle) {
    Map<String, Map<String, Field>> categorized = new HashMap<>();

    Map<String, Field> fields = Configuration.getConfigurationFields();
    String[] keys = new String[fields.size()];
    keys = fields.keySet().toArray(keys);
    Arrays.sort(keys);

    for (String name : keys) {
      Field field = fields.get(name);
      ConfigurationCategory cat = field.getAnnotation(ConfigurationCategory.class);
      String scat = cat == null ? "other" : cat.value();
      if (!categorized.containsKey(scat)) {
        categorized.put(scat, new HashMap<>());
      }

      categorized.get(scat).put(name, field);
    }

    for (String cat : categorized.keySet()) {
      JPanel configPanel = new JPanel(new SpringLayout());
      int itemCount = 0;
      for (String name : categorized.get(cat).keySet()) {
        Field field = categorized.get(cat).get(name);

        String locName = resourceBundle.getString("config.name." + name);

        try {
          ConfigurationItem item = (ConfigurationItem) field.get(null);

          ParameterizedType listType = (ParameterizedType) field.getGenericType();
          java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0];
          if (!(itemType2 instanceof Class<?>)) {
            continue;
          }

          Class itemType = (Class<?>) itemType2;

          String description = resourceBundle.getString("config.description." + name);

          Object defaultValue = Configuration.getDefaultValue(field);
          if (name.equals("gui.skin")) {
            Class c;
            try {
              c = Class.forName((String) defaultValue);
              defaultValue = c.getField("NAME").get(c);
            } catch (ClassNotFoundException | NoSuchFieldException | SecurityException ex) {
              Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex);
            }
          }

          if (defaultValue != null) {
            description += " (" + resourceBundle.getString("default") + ": " + defaultValue + ")";
          }

          JLabel l = new JLabel(locName, JLabel.TRAILING);
          l.setToolTipText(description);
          configPanel.add(l);
          Component c = null;
          if (name.equals("gui.skin")) {
            skinComboBox.setToolTipText(description);
            skinComboBox.setMaximumSize(
                new Dimension(Integer.MAX_VALUE, skinComboBox.getPreferredSize().height));
            c = skinComboBox;
          } else if ((itemType == String.class)
              || (itemType == Integer.class)
              || (itemType == Long.class)
              || (itemType == Double.class)
              || (itemType == Float.class)
              || (itemType == Calendar.class)) {
            JTextField tf = new JTextField();
            Object val = item.get();
            if (val == null) {
              val = "";
            }
            if (itemType == Calendar.class) {
              tf.setText(new SimpleDateFormat().format(((Calendar) item.get()).getTime()));
            } else {
              tf.setText(val.toString());
            }
            tf.setToolTipText(description);
            tf.setMaximumSize(new Dimension(Integer.MAX_VALUE, tf.getPreferredSize().height));
            c = tf;
          } else if (itemType == Boolean.class) {
            JCheckBox cb = new JCheckBox();
            cb.setSelected((Boolean) item.get());
            cb.setToolTipText(description);
            c = cb;
          } else if (itemType.isEnum()) {
            JComboBox<String> cb = new JComboBox<>();
            @SuppressWarnings("unchecked")
            EnumSet enumValues = EnumSet.allOf(itemType);
            String stringValue = null;
            for (Object enumValue : enumValues) {
              String enumValueStr = enumValue.toString();
              if (stringValue == null) {
                stringValue = enumValueStr;
              }
              cb.addItem(enumValueStr);
            }
            if (item.get() != null) {
              stringValue = item.get().toString();
            }
            cb.setToolTipText(description);
            cb.setSelectedItem(stringValue);
            cb.setMaximumSize(new Dimension(Integer.MAX_VALUE, cb.getPreferredSize().height));
            c = cb;
          } else {
            throw new UnsupportedOperationException(
                "Configuration ttem type '" + itemType.getName() + "' is not supported");
          }

          componentsMap.put(name, c);
          l.setLabelFor(c);
          configPanel.add(c);
        } catch (IllegalArgumentException | IllegalAccessException ex) {
          // Reflection exceptions. This should never happen
          throw new Error(ex.getMessage());
        }

        itemCount++;
      }

      SpringUtilities.makeCompactGrid(
          configPanel,
          itemCount,
          2, // rows, cols
          6,
          6, // initX, initY
          6,
          6); // xPad, yPad
      tabs.put(cat, new JScrollPane(configPanel));
    }
  }
  public List<File> exportAS2Scripts(
      AbortRetryIgnoreHandler handler,
      String outdir,
      Map<String, ASMSource> asms,
      ScriptExportSettings exportSettings,
      boolean parallel,
      EventListener evl)
      throws IOException {
    List<File> ret = new ArrayList<>();
    if (!outdir.endsWith(File.separator)) {
      outdir += File.separator;
    }

    Map<String, List<String>> existingNamesMap = new HashMap<>();
    int cnt = 1;
    List<ExportScriptTask> tasks = new ArrayList<>();
    String[] keys = asms.keySet().toArray(new String[asms.size()]);
    Arrays.sort(keys);
    for (String key : keys) {
      ASMSource asm = asms.get(key);
      String currentOutDir = outdir + key + File.separator;
      currentOutDir = new File(currentOutDir).getParentFile().toString() + File.separator;

      List<String> existingNames = existingNamesMap.get(currentOutDir);
      if (existingNames == null) {
        existingNames = new ArrayList<>();
        existingNamesMap.put(currentOutDir, existingNames);
      }

      String name = Helper.makeFileName(asm.getExportFileName());
      int i = 1;
      String baseName = name;
      while (existingNames.contains(name)) {
        i++;
        name = baseName + "_" + i;
      }
      existingNames.add(name);

      tasks.add(
          new ExportScriptTask(
              handler, cnt++, asms.size(), name, asm, currentOutDir, exportSettings, evl));
    }

    if (!parallel || tasks.size() < 2) {
      try {
        CancellableWorker.call(
            new Callable<Void>() {
              @Override
              public Void call() throws Exception {
                for (ExportScriptTask task : tasks) {
                  if (Thread.currentThread().isInterrupted()) {
                    throw new InterruptedException();
                  }

                  ret.add(task.call());
                }
                return null;
              }
            },
            Configuration.exportTimeout.get(),
            TimeUnit.SECONDS);
      } catch (TimeoutException ex) {
        logger.log(
            Level.SEVERE,
            Helper.formatTimeToText(Configuration.exportTimeout.get())
                + " ActionScript export limit reached",
            ex);
      } catch (ExecutionException | InterruptedException ex) {
        logger.log(Level.SEVERE, "Error during AS2 export", ex);
      }
    } else {
      ExecutorService executor =
          Executors.newFixedThreadPool(Configuration.getParallelThreadCount());
      List<Future<File>> futureResults = new ArrayList<>();
      for (ExportScriptTask task : tasks) {
        Future<File> future = executor.submit(task);
        futureResults.add(future);
      }

      try {
        executor.shutdown();
        if (!executor.awaitTermination(Configuration.exportTimeout.get(), TimeUnit.SECONDS)) {
          logger.log(
              Level.SEVERE,
              Helper.formatTimeToText(Configuration.exportTimeout.get())
                  + " ActionScript export limit reached");
        }
      } catch (InterruptedException ex) {
      } finally {
        executor.shutdownNow();
      }

      for (int f = 0; f < futureResults.size(); f++) {
        try {
          if (futureResults.get(f).isDone()) {
            ret.add(futureResults.get(f).get());
          }
        } catch (InterruptedException ex) {
        } catch (ExecutionException ex) {
          logger.log(Level.SEVERE, "Error during ABC export", ex);
        }
      }
    }

    return ret;
  }