content: package org.netbeans.modules.python.projectproperties;
  
  import java.io.FileWriter;
  import java.io.IOException;
  import java.nio.file.Paths;
  import java.util.Properties;
  import javax.swing.JFileChooser;
  import javax.swing.event.DocumentEvent;
  import javax.swing.event.DocumentListener;
  import org.netbeans.modules.python.PythonUtility;
  import org.netbeans.modules.python.project.PythonProject;
  import org.netbeans.modules.python.project.PythonProjectStateHandler;
  import org.openide.filesystems.FileObject;
  import org.openide.filesystems.FileUtil;
  import org.openide.util.Exceptions;
  
  /**
   *
   * @author albilu
   */
  public class PythonTestPanel extends javax.swing.JPanel implements DocumentListener {
  
      private static final long serialVersionUID = 1L;
  
      PythonProject project;
  
      /**
       * Creates new form PythonTestPanel
       */
      public PythonTestPanel(PythonProject project) {
          initComponents();
          testFrameworkComboBox.setRenderer(new PythonFrameworkCellRenderer());
          testGeneratorComboBox.setRenderer(new PythonFrameworkCellRenderer());
          testFrameworkParamsTextField.getDocument().addDocumentListener(this);
          testGeneratorDirTextField.getDocument().addDocumentListener(this);
          this.project = project;
          loadProperties();
      }
  
      /**
       * This method is called from within the constructor to initialize the form.
       * WARNING: Do NOT modify this code. The content of this method is always
       * regenerated by the Form Editor.
       */
      @SuppressWarnings("unchecked")
      // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
      private void initComponents() {
  
          testFrameworkChooserFileChooser = new javax.swing.JFileChooser();
          testGeneratorChooserFileChooser = new javax.swing.JFileChooser();
          testGeneratorPanel = new javax.swing.JPanel();
          testGeneratorLabel = new javax.swing.JLabel();
          testGeneratorComboBox = new javax.swing.JComboBox<>();
          testGeneratorParamsLabel = new javax.swing.JLabel();
          testGeneratorParamsTextField = new javax.swing.JTextField();
          testGeneratorDirLabel = new javax.swing.JLabel();
          testGeneratorDirTextField = new javax.swing.JTextField();
          testGeneratorDirButton = new javax.swing.JButton();
          testFrameworkPanel = new javax.swing.JPanel();
          testFrameworkLabel = new javax.swing.JLabel();
          testFrameworkParamsLabel = new javax.swing.JLabel();
          testFrameworkComboBox = new javax.swing.JComboBox<>();
          testFrameworkParamsTextField = new javax.swing.JTextField();
          testFrameworkDirLabel = new javax.swing.JLabel();
          testFrameworkDirTextField = new javax.swing.JTextField();
          testDirButton = new javax.swing.JButton();
  
          testFrameworkChooserFileChooser.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
          testFrameworkChooserFileChooser.setFileSelectionMode(javax.swing.JFileChooser.DIRECTORIES_ONLY);
  
          testGeneratorChooserFileChooser.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
          testGeneratorChooserFileChooser.setFileSelectionMode(javax.swing.JFileChooser.DIRECTORIES_ONLY);
  
          setLayout(new java.awt.BorderLayout());
  
          testGeneratorPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 1, 12))); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testGeneratorLabel, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorLabel.text")); // NOI18N
  
          testGeneratorComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "pynguin" }));
          testGeneratorComboBox.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  testGeneratorComboBoxActionPerformed(evt);
              }
          });
  
          org.openide.awt.Mnemonics.setLocalizedText(testGeneratorParamsLabel, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorParamsLabel.text")); // NOI18N
  
          testGeneratorParamsTextField.setText(org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorParamsTextField.text")); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testGeneratorDirLabel, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorDirLabel.text")); // NOI18N
  
          testGeneratorDirTextField.setText(org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorDirTextField.text")); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testGeneratorDirButton, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testGeneratorDirButton.text")); // NOI18N
          testGeneratorDirButton.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  testGeneratorDirButtonActionPerformed(evt);
              }
          });
  
          javax.swing.GroupLayout testGeneratorPanelLayout = new javax.swing.GroupLayout(testGeneratorPanel);
          testGeneratorPanel.setLayout(testGeneratorPanelLayout);
          testGeneratorPanelLayout.setHorizontalGroup(
              testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(testGeneratorPanelLayout.createSequentialGroup()
                  .addContainerGap()
                  .addGroup(testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addComponent(testGeneratorLabel)
                      .addComponent(testGeneratorParamsLabel)
                      .addComponent(testGeneratorDirLabel))
                  .addGap(24, 24, 24)
                  .addGroup(testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addComponent(testGeneratorParamsTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
                      .addGroup(testGeneratorPanelLayout.createSequentialGroup()
                          .addComponent(testGeneratorDirTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 323, Short.MAX_VALUE)
                          .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                          .addComponent(testGeneratorDirButton))
                      .addComponent(testGeneratorComboBox, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                  .addContainerGap())
          );
          testGeneratorPanelLayout.setVerticalGroup(
              testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(testGeneratorPanelLayout.createSequentialGroup()
                  .addGroup(testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(testGeneratorLabel)
                      .addComponent(testGeneratorComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addGroup(testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(testGeneratorParamsLabel)
                      .addComponent(testGeneratorParamsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addGroup(testGeneratorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(testGeneratorDirLabel)
                      .addComponent(testGeneratorDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                      .addComponent(testGeneratorDirButton))
                  .addGap(0, 0, Short.MAX_VALUE))
          );
  
          add(testGeneratorPanel, java.awt.BorderLayout.CENTER);
  
          testFrameworkPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testFrameworkPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 1, 12))); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testFrameworkLabel, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testFrameworkLabel.text")); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testFrameworkParamsLabel, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testFrameworkParamsLabel.text")); // NOI18N
  
          testFrameworkComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "unittest", "pytest" }));
          testFrameworkComboBox.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  testFrameworkComboBoxActionPerformed(evt);
              }
          });
  
          testFrameworkParamsTextField.setText(org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testFrameworkParamsTextField.text")); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testFrameworkDirLabel, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testFrameworkDirLabel.text")); // NOI18N
  
          testFrameworkDirTextField.setText(org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testFrameworkDirTextField.text")); // NOI18N
  
          org.openide.awt.Mnemonics.setLocalizedText(testDirButton, org.openide.util.NbBundle.getMessage(PythonTestPanel.class, "PythonTestPanel.testDirButton.text")); // NOI18N
          testDirButton.addActionListener(new java.awt.event.ActionListener() {
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  testDirButtonActionPerformed(evt);
              }
          });
  
          javax.swing.GroupLayout testFrameworkPanelLayout = new javax.swing.GroupLayout(testFrameworkPanel);
          testFrameworkPanel.setLayout(testFrameworkPanelLayout);
          testFrameworkPanelLayout.setHorizontalGroup(
              testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(testFrameworkPanelLayout.createSequentialGroup()
                  .addContainerGap()
                  .addGroup(testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addComponent(testFrameworkDirLabel)
                      .addComponent(testFrameworkParamsLabel)
                      .addComponent(testFrameworkLabel))
                  .addGap(55, 55, 55)
                  .addGroup(testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, testFrameworkPanelLayout.createSequentialGroup()
                          .addComponent(testFrameworkDirTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 296, Short.MAX_VALUE)
                          .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                          .addComponent(testDirButton))
                      .addGroup(testFrameworkPanelLayout.createSequentialGroup()
                          .addComponent(testFrameworkParamsTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 379, Short.MAX_VALUE)
                          .addGap(1, 1, 1))
                      .addComponent(testFrameworkComboBox, 0, 380, Short.MAX_VALUE))
                  .addContainerGap())
          );
          testFrameworkPanelLayout.setVerticalGroup(
              testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(testFrameworkPanelLayout.createSequentialGroup()
                  .addGroup(testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(testFrameworkLabel)
                      .addComponent(testFrameworkComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addGroup(testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(testFrameworkParamsLabel)
                      .addComponent(testFrameworkParamsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addGroup(testFrameworkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                      .addComponent(testFrameworkDirLabel)
                      .addComponent(testFrameworkDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                      .addComponent(testDirButton))
                  .addGap(0, 0, Short.MAX_VALUE))
          );
  
          add(testFrameworkPanel, java.awt.BorderLayout.PAGE_START);
      }// </editor-fold>//GEN-END:initComponents
  
      private void testDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testDirButtonActionPerformed
          testFrameworkChooserFileChooser.setCurrentDirectory(FileUtil
                  .toFile(project.getProjectDirectory()));
          int returnValue = testFrameworkChooserFileChooser.showSaveDialog(null);
          if (returnValue == JFileChooser.APPROVE_OPTION) {
              testFrameworkDirTextField.setText(testFrameworkChooserFileChooser
                      .getSelectedFile().toPath().toString());
              markChange();
          }
      }//GEN-LAST:event_testDirButtonActionPerformed
  
      private void testGeneratorDirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testGeneratorDirButtonActionPerformed
          testGeneratorChooserFileChooser.setCurrentDirectory(FileUtil
                  .toFile(project.getProjectDirectory()));
          int returnValue = testGeneratorChooserFileChooser.showSaveDialog(null);
          if (returnValue == JFileChooser.APPROVE_OPTION) {
              testGeneratorDirTextField.setText(testGeneratorChooserFileChooser
                      .getSelectedFile().toPath().toString());
              markChange();
          }
      }//GEN-LAST:event_testGeneratorDirButtonActionPerformed
  
      private void testFrameworkComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testFrameworkComboBoxActionPerformed
          markChange();
      }//GEN-LAST:event_testFrameworkComboBoxActionPerformed
  
      private void testGeneratorComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testGeneratorComboBoxActionPerformed
          markChange();
      }//GEN-LAST:event_testGeneratorComboBoxActionPerformed
  
      // Variables declaration - do not modify//GEN-BEGIN:variables
      private javax.swing.JButton testDirButton;
      private javax.swing.JFileChooser testFrameworkChooserFileChooser;
      public static javax.swing.JComboBox<String> testFrameworkComboBox;
      private javax.swing.JLabel testFrameworkDirLabel;
      private static javax.swing.JTextField testFrameworkDirTextField;
      private javax.swing.JLabel testFrameworkLabel;
      private javax.swing.JPanel testFrameworkPanel;
      private javax.swing.JLabel testFrameworkParamsLabel;
      private static javax.swing.JTextField testFrameworkParamsTextField;
      private javax.swing.JFileChooser testGeneratorChooserFileChooser;
      private static javax.swing.JComboBox<String> testGeneratorComboBox;
      private javax.swing.JButton testGeneratorDirButton;
      private javax.swing.JLabel testGeneratorDirLabel;
      private static javax.swing.JTextField testGeneratorDirTextField;
      private javax.swing.JLabel testGeneratorLabel;
      private javax.swing.JPanel testGeneratorPanel;
      private javax.swing.JLabel testGeneratorParamsLabel;
      private static javax.swing.JTextField testGeneratorParamsTextField;
      // End of variables declaration//GEN-END:variables
  
      private void loadProperties() {
          try {
              Properties prop = PythonUtility.getProperties(project, false);
              FileObject fileObject = project.getProjectDirectory()
                      .getFileObject("tests");
              FileObject fileObjectG = project.getProjectDirectory()
                      .getFileObject("tests/pynguin-tests");
              testFrameworkComboBox.setSelectedItem(prop
                      .getProperty("nbproject.test.runner", "print"));
              testFrameworkParamsTextField.setText(prop.
                      getProperty("nbproject.test.params", ""));
              testFrameworkDirTextField.setText(prop
                      .getProperty("nbproject.test.dir", fileObject != null
                              ? Paths.get(fileObject.getPath()).toString() : ""));
              testGeneratorDirTextField.setText(prop
                      .getProperty("nbproject.test.generator.dir", fileObjectG != null
                              ? Paths.get(fileObjectG.getPath()).toString() : ""));
              testGeneratorComboBox.setSelectedIndex(0);
              testGeneratorParamsTextField.setText(prop
                      .getProperty("nbproject.test.generator.params", ""));
          } catch (IOException ex) {
              Exceptions.printStackTrace(ex);
          }
      }
  
      public static void setProperties(PythonProject project) {
          try {
              Properties prop = PythonUtility.getProperties(project, false);
              prop.setProperty("nbproject.test.runner", testFrameworkComboBox.getSelectedItem().toString());
              prop.setProperty("nbproject.test.params", testFrameworkParamsTextField.getText());
              prop.setProperty("nbproject.test.dir", testFrameworkDirTextField.getText());
              prop.setProperty("nbproject.test.generator.dir", testGeneratorDirTextField.getText());
              prop.setProperty("nbproject.test.generator.runner", testGeneratorComboBox.getSelectedItem().toString());
              prop.setProperty("nbproject.test.generator.params", testGeneratorParamsTextField.getText());
              prop.store(new FileWriter(FileUtil.toFile(project.getProjectDirectory()
                      .getFileObject("nbproject/project.properties"))), null);
          } catch (IOException ex) {
              Exceptions.printStackTrace(ex);
          }
      }
  
      void markChange() {
          project.getLookup().lookup(PythonProjectStateHandler.class).mark();
      }
  
      @Override
      public void insertUpdate(DocumentEvent de) {
          markChange();
      }
  
      @Override
      public void removeUpdate(DocumentEvent de) {
          markChange();
      }
  
      @Override
      public void changedUpdate(DocumentEvent de) {
          markChange();
      }
  
  }
  