/**
 * GmailAssistant 1.1 (2008-03-16)
 * Copyright 2008 Zach Scrivena
 * zachscrivena@gmail.com
 * http://gmailassistant.sourceforge.net/
 *
 * Notifier for multiple Gmail accounts.
 *
 * TERMS AND CONDITIONS:
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation.
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

package gmailassistant;

import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.DocumentEvent;


/**
 * "Options" form.
 */
public class Options
        extends JFrame
{
    /** parent GmailAssistant object */
    private final GmailAssistant parent;

    /** are the "General" options selection valid? */
    private volatile boolean generalOptionsValid = false;

    /** are the "Proxy" options selection valid? */
    private volatile boolean proxyOptionsValid = false;

    /** are the "Mail Check" options selection valid? */
    private volatile boolean mailCheckOptionsValid = false;

    /** are the "Alerts" options selection valid? */
    private volatile boolean alertsOptionsValid = false;


    /**
    * Constructor.
    *
    * @param parent
    *      parent GmailAssistant object
    */
    Options(
            final GmailAssistant parent)
    {
        /*********************
        * INITIALIZE FIELDS *
        *********************/

        this.parent = parent;

        /******************************
        * INITIALIZE FORM COMPONENTS *
        ******************************/

        initComponents();

        /***************************
        * CONFIGURE FORM SETTINGS *
        ***************************/

        setTitle("Options - " + this.parent.getTitle());

        addWindowListener(new WindowAdapter()
        {
            @Override
            public void windowClosing(WindowEvent e)
            {
                Options.this.cancelButton.doClick();
            }
        });

        /* inherit "always on top" behavior of parent */
        try
        {
            setAlwaysOnTop(this.parent.isAlwaysOnTop());
        }
        catch (Exception e)
        {
            /* ignore */
        }

        /* inherit program icon of parent */
        final List<Image> icons = this.parent.getIconImages();

        if (!icons.isEmpty())
        {
            setIconImage(icons.get(0));
        }

        /* populate the "Options" form */
        repopulateOptions();

        /* "General" options */

        /* "Proxy" options */
        final JTextField[] proxyFields = new JTextField[]
        {
            this.proxyHostField,
            this.proxyPortField,
            this.proxyUsernameField,
            this.proxyPasswordField
        };

        for (JTextField f : proxyFields)
        {
            f.getDocument().addDocumentListener(new DocumentListenerAdapter()
            {
                @Override
                public void insertUpdate(DocumentEvent e)
                {
                    checkProxyOptions();
                }

                @Override
                public void removeUpdate(DocumentEvent e)
                {
                    checkProxyOptions();
                }

                @Override
                public void changedUpdate(DocumentEvent e)
                {
                    checkProxyOptions();
                }
            });
        }

        /* "Mail Check" options */
        this.mailField.getDocument().addDocumentListener(new DocumentListenerAdapter()
        {
            @Override
            public void insertUpdate(DocumentEvent e)
            {
                checkMailCheckOptions();
            }

            @Override
            public void removeUpdate(DocumentEvent e)
            {
                checkMailCheckOptions();
            }

            @Override
            public void changedUpdate(DocumentEvent e)
            {
                checkMailCheckOptions();
            }
        });

        /* "Alerts" options */
        this.bellField.getDocument().addDocumentListener(new DocumentListenerAdapter()
        {
            @Override
            public void insertUpdate(DocumentEvent e)
            {
                checkAlertsOptions();
            }

            @Override
            public void removeUpdate(DocumentEvent e)
            {
                checkAlertsOptions();
            }

            @Override
            public void changedUpdate(DocumentEvent e)
            {
                checkAlertsOptions();
            }
        });

        /* button: "OK" */
        this.okButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                acceptOptions();
            }
        });

        /* button: "Cancel" */
        this.cancelButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                cancelOptions();
            }
        });

        /* add standard editing popup menu to text fields */
        SwingManipulator.addStandardEditingPopupMenu(new JTextField[]
        {
            this.proxyHostField,
            this.proxyPortField,
            this.proxyUsernameField,
            this.proxyPasswordField,
            this.mailField,
            this.bellField
        });

        /* key binding: ENTER key */
        this.tabbedPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER_OK_BUTTON");

        this.tabbedPane.getActionMap().put("ENTER_OK_BUTTON", new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                Options.this.okButton.doClick();
            }
        });

        /* key binding: ESCAPE key */
        this.tabbedPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "ESCAPE_CANCEL_BUTTON");

        this.tabbedPane.getActionMap().put("ESCAPE_CANCEL_BUTTON", new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                Options.this.cancelButton.doClick();
            }
        });

        /* center form on the parent form */
        setLocationRelativeTo(this.parent);
    }


    /**
    * Accept changes and close the "Options" form.
    */
    private void acceptOptions()
    {
        /* revalidate options */
        checkGeneralOptions();
        checkProxyOptions();
        checkMailCheckOptions();
        checkAlertsOptions();

        if (this.generalOptionsValid &&
                this.proxyOptionsValid &&
                this.mailCheckOptionsValid &&
                this.alertsOptionsValid)
        {
            /* all options are valid */

            /* "General" options */
            this.parent.setProperty(GmailAssistant.Property.ALWAYS_ON_TOP, this.topBox.isSelected());

            /* "Proxy" options */
            this.parent.setProperty(GmailAssistant.Property.PROXY_HOST, this.proxyHostField.getText());
            this.parent.setProperty(GmailAssistant.Property.PROXY_PORT, this.proxyPortField.getText());
            this.parent.setProperty(GmailAssistant.Property.PROXY_USERNAME, this.proxyUsernameField.getText());
            this.parent.setProperty(GmailAssistant.Property.PROXY_PASSWORD, SwingManipulator.getPasswordJPasswordField(this.proxyPasswordField));

            /* "Mail Check" options */
            this.parent.setProperty(GmailAssistant.Property.MAIL_CHECK_INTERVAL_MILLISECONDS, Long.parseLong(this.mailField.getText()));

            /* "Alerts" options */
            this.parent.setProperty(GmailAssistant.Property.ALERT_POPUP_PERSISTENT_MESSAGES, this.persistentBox.isSelected());
            this.parent.setProperty(GmailAssistant.Property.ALERT_PERIODIC_BELL_INTERVAL_MILLISECONDS, Long.parseLong(this.bellField.getText()));

            this.setVisible(false);
        }
    }


    /**
    * Cancel changes and close the "Options" form.
    */
    private void cancelOptions()
    {
        repopulateOptions();
        this.setVisible(false);
    }


    /**
    * Repopulate the "Options" form according to the program properties.
    */
    void repopulateOptions()
    {
        /* "General" options */
        this.topBox.setSelected((Boolean) this.parent.getProperty(GmailAssistant.Property.ALWAYS_ON_TOP));

        /* "Proxy" options */
        this.proxyHostField.setText((String) this.parent.getProperty(GmailAssistant.Property.PROXY_HOST));
        this.proxyPortField.setText((String) this.parent.getProperty(GmailAssistant.Property.PROXY_PORT));
        this.proxyUsernameField.setText((String) this.parent.getProperty(GmailAssistant.Property.PROXY_USERNAME));
        this.proxyPasswordField.setText(String.valueOf((char[]) this.parent.getProperty(GmailAssistant.Property.PROXY_PASSWORD)));

        /* "Mail Check" options */
        this.mailField.setText(((Long) this.parent.getProperty(GmailAssistant.Property.MAIL_CHECK_INTERVAL_MILLISECONDS)).toString());

        /* "Alerts" options */
        this.persistentBox.setSelected((Boolean) this.parent.getProperty(GmailAssistant.Property.ALERT_POPUP_PERSISTENT_MESSAGES));
        this.bellField.setText(((Long) this.parent.getProperty(GmailAssistant.Property.ALERT_PERIODIC_BELL_INTERVAL_MILLISECONDS)).toString());

        /* validate options */
        checkGeneralOptions();
        checkProxyOptions();
        checkMailCheckOptions();
        checkAlertsOptions();
    }


    /**
    * Check "General" options specified by the user.
    * This method must run on the EDT.
    */
    private void checkGeneralOptions()
    {
        String error = null;

        if (error != null)
        {
            this.generalError.setText("<html><font color='red'>" + error + "</font></html>");
            this.okButton.setEnabled(false);
            this.generalOptionsValid = false;
            return;
        }

        this.generalOptionsValid = true;
        this.generalError.setText(" ");

        if (this.generalOptionsValid &&
                this.proxyOptionsValid &&
                this.mailCheckOptionsValid &&
                this.alertsOptionsValid)
        {
            /* all options are valid */
            this.okButton.setEnabled(true);
        }
    }


    /**
    * Check "Proxy" options specified by the user.
    * This method must run on the EDT.
    */
    private void checkProxyOptions()
    {
        String error = null;

        final String host = SwingManipulator.getTextJTextField(this.proxyHostField).trim();
        final String port = SwingManipulator.getTextJTextField(this.proxyPortField).trim();
        final String username = SwingManipulator.getTextJTextField(this.proxyUsernameField).trim();
        final char[] password = SwingManipulator.getPasswordJPasswordField(this.proxyPasswordField);
        final int passwordLength = password.length;
        Arrays.fill(password, '\0');

        if (host.isEmpty() != port.isEmpty())
        {
            error = "Both proxy host and port must be specified";
        }
        else if (username.isEmpty() && (passwordLength > 0))
        {
            error = "Proxy username must be specified if password is specified";
        }
        else if (!port.isEmpty())
        {
            try
            {
                if (Integer.parseInt(port) < 0)
                {
                    error = "Proxy port must be a nonnegative integer";
                }
            }
            catch (NumberFormatException e)
            {
                error = "Proxy port must be a nonnegative integer";
            }
        }

        if (error != null)
        {
            this.proxyError.setText("<html><font color='red'>" + error + "</font></html>");
            this.okButton.setEnabled(false);
            this.proxyOptionsValid = false;
            return;
        }

        this.proxyOptionsValid = true;
        this.proxyError.setText(" ");

        if (this.generalOptionsValid &&
                this.proxyOptionsValid &&
                this.mailCheckOptionsValid &&
                this.alertsOptionsValid)
        {
            /* all options are valid */
            this.okButton.setEnabled(true);
        }
    }


    /**
    * Check "Mail Check" options specified by the user.
    * This method must run on the EDT.
    */
    private void checkMailCheckOptions()
    {
        String error = null;

        final String mail = SwingManipulator.getTextJTextField(this.mailField).trim();

        if (mail.isEmpty())
        {
            error = "Mail check interval must not be empty";
        }
        else
        {
            try
            {
                if (Long.parseLong(mail) < 0)
                {
                    error = "Mail check interval must be a nonnegative integer";
                }
            }
            catch (NumberFormatException e)
            {
                error = "Mail check interval must be a nonnegative integer";
            }
        }

        if (error != null)
        {
            this.mailCheckError.setText("<html><font color='red'>" + error + "</font></html>");
            this.okButton.setEnabled(false);
            this.mailCheckOptionsValid = false;
            return;
        }

        this.mailCheckOptionsValid = true;
        this.mailCheckError.setText(" ");

        if (this.generalOptionsValid &&
                this.proxyOptionsValid &&
                this.mailCheckOptionsValid &&
                this.alertsOptionsValid)
        {
            /* all options are valid */
            this.okButton.setEnabled(true);
        }
    }


    /**
    * Check "Alerts" options specified by the user.
    * This method must run on the EDT.
    */
    private void checkAlertsOptions()
    {
        String error = null;

        final String bell = SwingManipulator.getTextJTextField(this.bellField).trim();

        if (bell.isEmpty())
        {
            error = "Periodic bell interval must not be empty";
        }
        else
        {
            try
            {
                if (Long.parseLong(bell) < 0)
                {
                    error = "Periodic bell interval must be a nonnegative integer";
                }
            }
            catch (NumberFormatException e)
            {
                error = "Periodic bell interval must be a nonnegative integer";
            }
        }

        if (error != null)
        {
            this.alertsError.setText("<html><font color='red'>" + error + "</font></html>");
            this.okButton.setEnabled(false);
            this.alertsOptionsValid = false;
            return;
        }

        this.alertsOptionsValid = true;
        this.alertsError.setText(" ");

        if (this.generalOptionsValid &&
                this.proxyOptionsValid &&
                this.mailCheckOptionsValid &&
                this.alertsOptionsValid)
        {
            /* all options are valid */
            this.okButton.setEnabled(true);
        }
    }


    /** 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.
    */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents()
    {

        tabbedPane = new javax.swing.JTabbedPane();
        generalPanel = new javax.swing.JPanel();
        topBox = new javax.swing.JCheckBox();
        generalError = new javax.swing.JLabel();
        proxyPanel = new javax.swing.JPanel();
        proxyLabel = new javax.swing.JLabel();
        proxyHostLabel = new javax.swing.JLabel();
        proxyHostField = new javax.swing.JTextField();
        proxyPortField = new javax.swing.JTextField();
        proxyPortLabel = new javax.swing.JLabel();
        proxyUsernameLabel = new javax.swing.JLabel();
        proxyPasswordLabel = new javax.swing.JLabel();
        proxyUsernameField = new javax.swing.JTextField();
        proxyPasswordField = new javax.swing.JPasswordField();
        proxyError = new javax.swing.JLabel();
        mailCheckPanel = new javax.swing.JPanel();
        mailLabel = new javax.swing.JLabel();
        mailField = new javax.swing.JTextField();
        mailCheckError = new javax.swing.JLabel();
        alertsPanel = new javax.swing.JPanel();
        bellLabel = new javax.swing.JLabel();
        bellField = new javax.swing.JTextField();
        persistentBox = new javax.swing.JCheckBox();
        alertsError = new javax.swing.JLabel();
        buttonsPanel = new javax.swing.JPanel();
        okButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);

        topBox.setMnemonic('T');
        topBox.setText("Always on top");
        topBox.setToolTipText("Keep the GmailAssistant windows above other programs on the desktop");

        generalError.setText("<html><font color='red'>General error</font></html>");

        javax.swing.GroupLayout generalPanelLayout = new javax.swing.GroupLayout(generalPanel);
        generalPanel.setLayout(generalPanelLayout);
        generalPanelLayout.setHorizontalGroup(
            generalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(generalPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(generalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(generalError, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
                    .addComponent(topBox))
                .addContainerGap())
        );
        generalPanelLayout.setVerticalGroup(
            generalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(generalPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(topBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 169, Short.MAX_VALUE)
                .addComponent(generalError)
                .addContainerGap())
        );

        tabbedPane.addTab("General", generalPanel);

        proxyLabel.setText("<html>GmailAssistant can use a proxy server that supports the SOCKS v4 or v5 protocol.<html>");

        proxyHostLabel.setDisplayedMnemonic('h');
        proxyHostLabel.setLabelFor(proxyHostField);
        proxyHostLabel.setText("Host:");
        proxyHostLabel.setToolTipText("SOCKS proxy host (e.g. socks.mydomain.com)");

        proxyHostField.setToolTipText("SOCKS proxy host (e.g. socks.mydomain.com)");

        proxyPortField.setToolTipText("SOCKS proxy port (e.g. 1080)");

        proxyPortLabel.setDisplayedMnemonic('t');
        proxyPortLabel.setLabelFor(proxyPortField);
        proxyPortLabel.setText("Port:");
        proxyPortLabel.setToolTipText("SOCKS proxy port (e.g. 1080)");

        proxyUsernameLabel.setDisplayedMnemonic('u');
        proxyUsernameLabel.setLabelFor(proxyUsernameField);
        proxyUsernameLabel.setText("Username:");
        proxyUsernameLabel.setToolTipText("SOCKS proxy username");

        proxyPasswordLabel.setDisplayedMnemonic('p');
        proxyPasswordLabel.setLabelFor(proxyPasswordField);
        proxyPasswordLabel.setText("Password:");
        proxyPasswordLabel.setToolTipText("SOCKS proxy password");

        proxyUsernameField.setToolTipText("SOCKS proxy username");

        proxyPasswordField.setToolTipText("SOCKS proxy password");

        proxyError.setText("<html><font color='red'>Proxy error</font></html>");

        javax.swing.GroupLayout proxyPanelLayout = new javax.swing.GroupLayout(proxyPanel);
        proxyPanel.setLayout(proxyPanelLayout);
        proxyPanelLayout.setHorizontalGroup(
            proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, proxyPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(proxyError, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
                    .addComponent(proxyLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, proxyPanelLayout.createSequentialGroup()
                        .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(proxyUsernameLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(proxyPortLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(proxyHostLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(proxyPasswordLabel, javax.swing.GroupLayout.Alignment.LEADING))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(proxyHostField, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE)
                            .addComponent(proxyPortField, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE)
                            .addComponent(proxyUsernameField, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE)
                            .addComponent(proxyPasswordField, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE))))
                .addContainerGap())
        );
        proxyPanelLayout.setVerticalGroup(
            proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(proxyPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(proxyLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(proxyHostLabel)
                    .addComponent(proxyHostField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(proxyPortLabel)
                    .addComponent(proxyPortField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(proxyUsernameLabel)
                    .addComponent(proxyUsernameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(proxyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(proxyPasswordLabel)
                    .addComponent(proxyPasswordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 22, Short.MAX_VALUE)
                .addComponent(proxyError)
                .addContainerGap())
        );

        tabbedPane.addTab("Proxy", proxyPanel);

        mailLabel.setDisplayedMnemonic('m');
        mailLabel.setLabelFor(mailField);
        mailLabel.setText("Mail check interval (milliseconds):");
        mailLabel.setToolTipText("Mail check interval in milliseconds");

        mailField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        mailField.setText("60000");
        mailField.setToolTipText("Mail check interval in milliseconds");

        mailCheckError.setText("<html><font color='red'>Mail check error</font></html>");

        javax.swing.GroupLayout mailCheckPanelLayout = new javax.swing.GroupLayout(mailCheckPanel);
        mailCheckPanel.setLayout(mailCheckPanelLayout);
        mailCheckPanelLayout.setHorizontalGroup(
            mailCheckPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mailCheckPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mailCheckPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(mailCheckError, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
                    .addGroup(mailCheckPanelLayout.createSequentialGroup()
                        .addComponent(mailLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(mailField, javax.swing.GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE)))
                .addContainerGap())
        );
        mailCheckPanelLayout.setVerticalGroup(
            mailCheckPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mailCheckPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mailCheckPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(mailLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(mailField, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 168, Short.MAX_VALUE)
                .addComponent(mailCheckError, javax.swing.GroupLayout.PREFERRED_SIZE,