class LanguageManagerDialog implements ActionListener {

  private final List<File> ruleFiles = new ArrayList<>();
  private final Frame owner;
  private final ResourceBundle messages;

  private JDialog dialog;
  private JList<File> list;
  private JButton addButton;
  private JButton removeButton;
  private JButton closeButton;

  public LanguageManagerDialog(Frame owner, List<Language> languages) {
    this.owner = owner;
    for (Language lang : languages) {
      for (String ruleFile : lang.getRuleFileNames()) {
        ruleFiles.add(new File(ruleFile));
      }
    }
    messages = JLanguageTool.getMessageBundle();
  }
  
  public void show() {<FILL_FUNCTION_BODY>}

  @Override
  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == addButton) {
      Configuration config;
      try {
        config = new Configuration(null);
      } catch (IOException e1) {
        throw new RuntimeException(e1);
      }
      File initialDir;
      File ruleFile;
      if (config.getExternalRuleDirectory() != null) {
        initialDir = new File(config.getExternalRuleDirectory());
        if (initialDir.isDirectory()) {
          ruleFile = Tools.openFileDialog(owner, new XMLFileFilter(), initialDir);
        } else {
          ruleFile = Tools.openFileDialog(owner, new XMLFileFilter());
        }
      } else {
          ruleFile = Tools.openFileDialog(owner, new XMLFileFilter());
      }
      if (ruleFile == null) {
        return; // dialog was canceled
      }
      config.setExternalRuleDirectory(ruleFile.getParent());
      try {
        config.saveConfiguration(null);
      } catch (IOException e1) {
        throw new RuntimeException(e1);
      }
      if (!ruleFiles.contains(ruleFile)) {
        ruleFiles.add(ruleFile);
        list.setListData(ruleFiles.toArray(new File[0]));
      } else {
        JOptionPane jop = new JOptionPane();
        JOptionPane.showMessageDialog(jop, messages.getString("guiDuplicate"),
                messages.getString("guiWarning"), JOptionPane.WARNING_MESSAGE);
      }
    } else if (e.getSource() == removeButton) {
      if (list.getSelectedIndex() != -1) {
        ruleFiles.remove(list.getSelectedIndex());
        list.setListData(ruleFiles.toArray(new File[0]));
      }
    } else if (e.getSource() == closeButton) {
      dialog.setVisible(false);
    } else {
      throw new IllegalArgumentException("Don't know how to handle " + e);
    }
  }
  
  /**
   * Return all external Languages.
   */
  List<Language> getLanguages() throws IllegalAccessException, InstantiationException {
    List<Language> languages = new ArrayList<>();
    for (File ruleFile : ruleFiles) {
      if (ruleFile != null) {
        Language newLanguage = LanguageBuilder.makeAdditionalLanguage(ruleFile);
        languages.add(newLanguage);
      }
    }
    return languages;
  }
  
  static class XMLFileFilter extends FileFilter {
    @Override
    public boolean accept(File f) {
      if (f.getName().startsWith("rules") && f.getName().toLowerCase().endsWith(".xml") 
              || f.isDirectory()) {
        return true;
      }
      return false;
    }
    @Override
    public String getDescription() {
      return "rules*.xml";
    }
  }

}

    dialog = new JDialog(owner, true);
    dialog.setTitle(messages.getString("guiLanguageManagerDialog"));
    
    // close dialog when user presses Escape key:
    // TODO: taken from ConfigurationDialog, avoid duplication:
    KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
    ActionListener actionListener = new ActionListener() {
      @Override
      @SuppressWarnings("unused")
      public void actionPerformed(ActionEvent actionEvent) {
        dialog.setVisible(false); 
      }
    };
    JRootPane rootPane = dialog.getRootPane();
    rootPane.registerKeyboardAction(actionListener, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);

    Container contentPane = dialog.getContentPane();
    contentPane.setLayout(new GridBagLayout());

    list = new JList<>(ruleFiles.toArray(new File[0]));
    GridBagConstraints cons = new GridBagConstraints();
    cons.insets = new Insets(4, 4, 4, 4);
    cons.gridx = 0;
    cons.gridy = 0;
    cons.fill = GridBagConstraints.BOTH;
    cons.weightx = 2.0f;
    cons.weighty = 2.0f;
    contentPane.add(new JScrollPane(list), cons);
    
    cons = new GridBagConstraints();
    cons.insets = new Insets(4, 4, 4, 4);
    cons.fill = GridBagConstraints.HORIZONTAL;
    
    JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new GridBagLayout());
    addButton = new JButton(messages.getString("guiAddButton"));
    addButton.addActionListener(this);
    cons.gridx = 1;
    cons.gridy = 0;
    buttonPanel.add(addButton, cons);

    removeButton = new JButton(messages.getString("guiRemoveButton"));
    removeButton.addActionListener(this);
    cons.gridx = 1;
    cons.gridy = 1;
    buttonPanel.add(removeButton, cons);

    closeButton = new JButton(messages.getString("guiCloseButton"));
    closeButton.addActionListener(this);
    cons.gridx = 1;
    cons.gridy = 2;
    buttonPanel.add(closeButton, cons);

    cons.gridx = 1;
    cons.gridy = 0;
    cons = new GridBagConstraints();
    cons.anchor = GridBagConstraints.NORTH;
    contentPane.add(buttonPanel, cons);
    
    dialog.pack();
    dialog.setSize(300, 200);
    dialog.setLocationByPlatform(true);
    dialog.setVisible(true);
  
<no_super_class>