au.com.jwatmuff.eventmanager.gui.main.LoadCompetitionWindow.java Source code

Java tutorial

Introduction

Here is the source code for au.com.jwatmuff.eventmanager.gui.main.LoadCompetitionWindow.java

Source

/*
 * EventManager
 * Copyright (c) 2008-2017 James Watmuff & Leonard Hall
 *
 * This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   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 au.com.jwatmuff.eventmanager.gui.main;

import au.com.jwatmuff.eventmanager.Main;
import au.com.jwatmuff.eventmanager.gui.admin.EnterPasswordDialog;
import au.com.jwatmuff.eventmanager.gui.license.LicenseKeyDialog;
import au.com.jwatmuff.eventmanager.gui.scoreboard.ScoreboardWindow;
import au.com.jwatmuff.eventmanager.permissions.Action;
import au.com.jwatmuff.eventmanager.permissions.License;
import au.com.jwatmuff.eventmanager.permissions.LicenseManager;
import au.com.jwatmuff.eventmanager.permissions.PermissionChecker;
import au.com.jwatmuff.eventmanager.util.DirUtils;
import au.com.jwatmuff.eventmanager.util.GUIUtils;
import au.com.jwatmuff.eventmanager.util.ZipUtils;
import au.com.jwatmuff.genericdb.p2p.DatabaseInfo;
import au.com.jwatmuff.genericdb.p2p.DatabaseManager;
import au.com.jwatmuff.genericp2p.PeerManager;
import java.awt.Component;
import java.awt.GridLayout;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

/**
 * This interface is the entry point to the EventManager program. It lists
 * all local and network competition databases, allowing the user to launch
 * the EventManager for one of these competitions or a brand new competition.
 *
 * @author  James
 */
public class LoadCompetitionWindow extends javax.swing.JFrame {
    private static Logger log = Logger.getLogger(LoadCompetitionWindow.class);
    private SimpleDateFormat dateFormat = new SimpleDateFormat();
    private PeerManager peerManager;

    private DatabaseManager dbManager;
    private LicenseManager licenseManager;

    private DatabaseInfo selected;
    private boolean isNew = false;
    private boolean success = false;

    private DefaultListModel<DatabaseInfo> dbListModel = new DefaultListModel<DatabaseInfo>();

    private static final int CHECK_DATABASES_PERIOD = 5000; //milliseconds

    private static final long MS_PER_DAY = 24 * 60 * 60 * 1000;

    private Runnable checkDatabasesTask = new Runnable() {
        @Override
        public void run() {
            updateDatabaseList();
        }
    };

    private ScheduledExecutorService checkDatabasesExecutor;

    /** Creates new form LoadCompetitionWindow */
    public LoadCompetitionWindow(DatabaseManager dbManager, LicenseManager licenseManager,
            PeerManager peerManager) {
        initComponents();
        setIconImage(Icons.MAIN_WINDOW.getImage());

        this.dbManager = dbManager;
        this.licenseManager = licenseManager;
        this.peerManager = peerManager;
        this.getRootPane().setDefaultButton(okButton);

        chatPanelContainer.setLayout(new GridLayout(1, 1));
        chatPanelContainer.add(new ChatPanel(peerManager));

        competitionList.setCellRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list, Object obj, int arg2, boolean arg3,
                    boolean arg4) {
                if (obj instanceof DatabaseInfo) {
                    DatabaseInfo di = (DatabaseInfo) obj;
                    JLabel label = (JLabel) super.getListCellRendererComponent(list, di.name, arg2, arg3, arg4);
                    label.setIcon((!Main.VERSION.equals(di.version)) ? Icons.NO
                            : (di.peers > 0) ? Icons.REMOTE : Icons.LOCAL);
                    return label;
                }
                return super.getListCellRendererComponent(list, obj, arg2, arg3, arg4);
            }

        });

        this.competitionList.setModel(dbListModel);
        updateDatabaseList();
        updateLicenseInfo();

        updateOkButton();

        // center window on screen
        setLocationRelativeTo(null);
    }

    @Override
    public void setVisible(boolean visible) {
        if (visible) {
            success = false;
            isNew = false;
            updateLicenseInfo();
            checkDatabasesExecutor = Executors.newSingleThreadScheduledExecutor();
            checkDatabasesExecutor.scheduleAtFixedRate(checkDatabasesTask, 0, CHECK_DATABASES_PERIOD,
                    TimeUnit.MILLISECONDS);
            dbManager.setListener(new DatabaseManager.Listener() {
                @Override
                public void handleDatabaseManagerEvent() {
                    updateDatabaseList();
                }
            });
        }
        super.setVisible(visible);
    }

    private void updateDatabaseList() {
        log.debug("Attempting to update database list");
        dbManager.updateAllDatabaseInfo();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                DatabaseInfo oldSelected = (DatabaseInfo) competitionList.getSelectedValue();
                dbListModel.clear();
                ArrayList<DatabaseInfo> dbinfo = new ArrayList<DatabaseInfo>(dbManager.getDatabases());
                Collections.sort(dbinfo, new Comparator<DatabaseInfo>() {
                    public int compare(DatabaseInfo dbinfo1, DatabaseInfo dbinfo2) {
                        return dbinfo1.name.compareTo(dbinfo2.name);
                    }
                });
                for (DatabaseInfo info : dbinfo)
                    dbListModel.addElement(info);

                boolean compsPresent = dbListModel.size() > 0;
                existingCompRadioButton.setEnabled(compsPresent);

                if (oldSelected != null) {
                    competitionList.setSelectedValue(oldSelected, true);
                }
            }
        });
    }

    private void updateLicenseInfo() {
        License license = licenseManager.getLicense();

        if (license == null) {
            licenseNameLabel.setText("N/A");
            licenseContactLabel.setText("N/A");
            licenseTypeLabel.setText("FREE");
            licenseExpiryLabel.setText("Never");
            expiryWarningLabel.setVisible(false);
        } else {
            licenseNameLabel.setText(license.getName());
            licenseContactLabel.setText(license.getContactPhoneNumber());
            licenseTypeLabel.setText(license.getType().toString());
            licenseExpiryLabel.setText(license.getExpiry().toString());

            long daysToExpiry = (license.getExpiry().getTime() - new Date().getTime()) / MS_PER_DAY;
            if (daysToExpiry > 0 && daysToExpiry <= 90) {
                expiryWarningLabel.setText("Your Event Manager license will expire in " + daysToExpiry + " day"
                        + ((daysToExpiry > 1) ? "s" : ""));
                expiryWarningLabel.setVisible(true);
            } else {
                expiryWarningLabel.setVisible(false);
            }
        }
        this.pack();
    }

    public boolean getSuccess() {
        return success;
    }

    public DatabaseInfo getSelectedDatabaseInfo() {
        return selected;
    }

    public boolean isNewDatabase() {
        return isNew;
    }

    private void updateOkButton() {
        if (newCompRadioButton.isSelected()) {
            okButton.setText("Create");
            okButton.setEnabled(true);
        } else if (existingCompRadioButton.isSelected()) {
            okButton.setText("Open");
            okButton.setEnabled(competitionList.getSelectedIndex() >= 0);
        }
    }

    @Override
    public void dispose() {
        dbManager.setListener(null);
        if (checkDatabasesExecutor != null)
            checkDatabasesExecutor.shutdownNow();
        super.dispose();
    }

    /** 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() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel3 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        existingCompRadioButton = new javax.swing.JRadioButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        competitionList = new javax.swing.JList<DatabaseInfo>();
        loadBackupButton = new javax.swing.JButton();
        saveBackupButton = new javax.swing.JButton();
        deleteCompButton = new javax.swing.JButton();
        renameCompButton = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        newCompRadioButton = new javax.swing.JRadioButton();
        cancelButton = new javax.swing.JButton();
        okButton = new javax.swing.JButton();
        expiryWarningLabel = new javax.swing.JLabel();
        jPanel4 = new javax.swing.JPanel();
        manualScoreboardButton = new javax.swing.JButton();
        displayScoreboardButton = new javax.swing.JButton();
        jPanel5 = new javax.swing.JPanel();
        jPanel6 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        licenseNameLabel = new javax.swing.JLabel();
        licenseContactLabel = new javax.swing.JLabel();
        licenseTypeLabel = new javax.swing.JLabel();
        licenseExpiryLabel = new javax.swing.JLabel();
        loadLicenseButton = new javax.swing.JButton();
        enterLicenseKeyButton = new javax.swing.JButton();
        chatPanelContainer = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Event Manager");
        setLocationByPlatform(true);
        setResizable(false);

        jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        buttonGroup1.add(existingCompRadioButton);
        existingCompRadioButton.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        existingCompRadioButton.setText("Open Existing Competition");
        existingCompRadioButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        existingCompRadioButton.setEnabled(false);
        existingCompRadioButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
        existingCompRadioButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                existingCompRadioButtonActionPerformed(evt);
            }
        });

        competitionList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        competitionList.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                competitionListMouseClicked(evt);
            }
        });
        competitionList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                competitionListValueChanged(evt);
            }
        });
        competitionList.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                competitionListFocusGained(evt);
            }
        });
        jScrollPane1.setViewportView(competitionList);

        loadBackupButton.setText("Load Backup..");
        loadBackupButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadBackupButtonActionPerformed(evt);
            }
        });

        saveBackupButton.setText("Save Backup..");
        saveBackupButton.setEnabled(false);
        saveBackupButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveBackupButtonActionPerformed(evt);
            }
        });

        deleteCompButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/famfamfam/icons/silk/delete.png"))); // NOI18N
        deleteCompButton.setText("Delete Competition");
        deleteCompButton.setEnabled(false);
        deleteCompButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteCompButtonActionPerformed(evt);
            }
        });

        renameCompButton
                .setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/famfamfam/icons/silk/delete.png"))); // NOI18N
        renameCompButton.setText("Rename");
        renameCompButton.setEnabled(false);
        renameCompButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                renameCompButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(jPanel2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(
                                        jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 572, Short.MAX_VALUE)
                                .addComponent(existingCompRadioButton)
                                .addGroup(jPanel2Layout.createSequentialGroup().addComponent(loadBackupButton)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(saveBackupButton)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(deleteCompButton)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(renameCompButton)))
                        .addContainerGap()));
        jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap()
                        .addComponent(existingCompRadioButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(loadBackupButton).addComponent(saveBackupButton)
                                .addComponent(deleteCompButton).addComponent(renameCompButton))
                        .addContainerGap()));

        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        buttonGroup1.add(newCompRadioButton);
        newCompRadioButton.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        newCompRadioButton.setSelected(true);
        newCompRadioButton.setText("Create New Competition");
        newCompRadioButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        newCompRadioButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
        newCompRadioButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newCompRadioButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout
                .setHorizontalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanel1Layout.createSequentialGroup().addContainerGap()
                                .addComponent(newCompRadioButton).addContainerGap(427, Short.MAX_VALUE)));
        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup().addContainerGap().addComponent(newCompRadioButton)
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        cancelButton.setText("Exit");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        okButton.setText("Open");
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });

        expiryWarningLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        expiryWarningLabel.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/com/famfamfam/icons/silk/exclamation.png"))); // NOI18N
        expiryWarningLabel.setText("Your EventManager license will expire in X days.");

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(jPanel3Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel3Layout.createSequentialGroup().addContainerGap().addGroup(jPanel3Layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
                                jPanel3Layout.createSequentialGroup()
                                        .addComponent(expiryWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 455,
                                                Short.MAX_VALUE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(okButton)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(cancelButton)))
                        .addContainerGap()));

        jPanel3Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
                new java.awt.Component[] { cancelButton, okButton });

        jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel3Layout.createSequentialGroup().addContainerGap()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addGroup(jPanel3Layout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(cancelButton, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(okButton, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addComponent(expiryWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addContainerGap()));

        jTabbedPane1.addTab("Start Competition", jPanel3);

        manualScoreboardButton.setIcon(new javax.swing.ImageIcon(
                getClass().getResource("/com/famfamfam/icons/silk/application_view_tile.png"))); // NOI18N
        manualScoreboardButton.setText("Manual Scoreboard Entry..");
        manualScoreboardButton.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        manualScoreboardButton.setIconTextGap(8);
        manualScoreboardButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                manualScoreboardButtonActionPerformed(evt);
            }
        });

        displayScoreboardButton.setIcon(new javax.swing.ImageIcon(
                getClass().getResource("/com/famfamfam/icons/silk/application_view_tile.png"))); // NOI18N
        displayScoreboardButton.setText("Manual Scoreboard Display..");
        displayScoreboardButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayScoreboardButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(jPanel4Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel4Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(manualScoreboardButton).addComponent(displayScoreboardButton))
                        .addContainerGap(415, Short.MAX_VALUE)));

        jPanel4Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
                new java.awt.Component[] { displayScoreboardButton, manualScoreboardButton });

        jPanel4Layout.setVerticalGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel4Layout.createSequentialGroup().addContainerGap()
                        .addComponent(manualScoreboardButton).addGap(18, 18, 18)
                        .addComponent(displayScoreboardButton).addContainerGap(360, Short.MAX_VALUE)));

        jTabbedPane1.addTab("Manual Interfaces", jPanel4);

        jPanel6.setBorder(javax.swing.BorderFactory.createTitledBorder("Current License"));

        jLabel1.setText("Name:");

        jLabel2.setText("Contact Phone:");

        jLabel3.setText("Level:");

        jLabel4.setText("Expiry:");

        licenseNameLabel.setText("N/A");

        licenseContactLabel.setText("N/A");

        licenseTypeLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        licenseTypeLabel.setText("FREE");

        licenseExpiryLabel.setText("N/A");

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(jPanel6Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel6Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(jPanel6Layout.createSequentialGroup().addComponent(jLabel1)
                                        .addGap(18, 18, 18).addComponent(licenseNameLabel))
                                .addGroup(jPanel6Layout.createSequentialGroup().addComponent(jLabel2)
                                        .addGap(18, 18, 18).addComponent(licenseContactLabel))
                                .addGroup(jPanel6Layout.createSequentialGroup().addComponent(jLabel3)
                                        .addGap(18, 18, 18).addComponent(licenseTypeLabel))
                                .addGroup(jPanel6Layout.createSequentialGroup().addComponent(jLabel4)
                                        .addGap(18, 18, 18).addComponent(licenseExpiryLabel)))
                        .addContainerGap(437, Short.MAX_VALUE)));

        jPanel6Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
                new java.awt.Component[] { jLabel1, jLabel2, jLabel3, jLabel4 });

        jPanel6Layout.setVerticalGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel6Layout.createSequentialGroup()
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel1).addComponent(licenseNameLabel,
                                        javax.swing.GroupLayout.PREFERRED_SIZE, 14,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel2).addComponent(licenseContactLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel3).addComponent(licenseTypeLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel4).addComponent(licenseExpiryLabel))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        loadLicenseButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/com/famfamfam/icons/silk/key_add.png"))); // NOI18N
        loadLicenseButton.setText("Load License File..");
        loadLicenseButton.setIconTextGap(8);
        loadLicenseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadLicenseButtonActionPerformed(evt);
            }
        });

        enterLicenseKeyButton.setIcon(
                new javax.swing.ImageIcon(getClass().getResource("/com/famfamfam/icons/silk/key_add.png"))); // NOI18N
        enterLicenseKeyButton.setText("Enter License Key..");
        enterLicenseKeyButton.setIconTextGap(8);
        enterLicenseKeyButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                enterLicenseKeyButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(jPanel5Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel5Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(jPanel5Layout.createSequentialGroup().addComponent(loadLicenseButton)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(enterLicenseKeyButton)))
                        .addContainerGap()));
        jPanel5Layout.setVerticalGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel5Layout.createSequentialGroup().addContainerGap()
                        .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(loadLicenseButton).addComponent(enterLicenseKeyButton))
                        .addContainerGap(288, Short.MAX_VALUE)));

        jTabbedPane1.addTab("Licenses", jPanel5);

        javax.swing.GroupLayout chatPanelContainerLayout = new javax.swing.GroupLayout(chatPanelContainer);
        chatPanelContainer.setLayout(chatPanelContainerLayout);
        chatPanelContainerLayout.setHorizontalGroup(chatPanelContainerLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 263, Short.MAX_VALUE));
        chatPanelContainerLayout.setVerticalGroup(chatPanelContainerLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 0, Short.MAX_VALUE));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(
                                layout.createSequentialGroup().addContainerGap()
                                        .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 629,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(chatPanelContainer, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                javax.swing.GroupLayout.Alignment.TRAILING,
                layout.createSequentialGroup().addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(jTabbedPane1, javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(chatPanelContainer, javax.swing.GroupLayout.Alignment.LEADING,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        Short.MAX_VALUE))
                        .addContainerGap()));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void competitionListMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_competitionListMouseClicked
        // handle double click on a list the same as pressing OK
        if (evt.getClickCount() == 2 && existingCompRadioButton.isSelected())
            okButtonActionPerformed(null);
    }//GEN-LAST:event_competitionListMouseClicked

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        this.dispose();
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        if (newCompRadioButton.isSelected()) {
            if (!PermissionChecker.isAllowed(Action.CREATE_COMPETITION, null))
                return;
            NewCompetitionDialog ncd = new NewCompetitionDialog(this, true);
            ncd.setVisible(true);
            if (ncd.getSuccess()) {
                selected = dbManager.createNewDatabase(ncd.getCompetitionName(), ncd.getPasswordHash());
                isNew = true;
                success = true;
                this.dispose();
                return;
            }
        }

        if (existingCompRadioButton.isSelected()) {
            selected = (DatabaseInfo) competitionList.getSelectedValue();
            if (selected == null)
                return;
            if (!Main.VERSION.equals(selected.version)) {
                GUIUtils.displayError(this, "This competition is only compatible with version " + selected.version
                        + ".\nThis copy of EventManager is version " + Main.VERSION + ".");
                return;
            }

            /* password check */
            if (!dbManager.authenticate(selected, 0)) {
                EnterPasswordDialog epd = new EnterPasswordDialog(this, true);
                epd.setActionText("Load Competition '" + selected.name + "'");
                epd.setPromptText("Connect password required");
                while (true) {
                    epd.setVisible(true);
                    if (epd.getSuccess()) {
                        int passwordHash = epd.getPassword().hashCode();
                        if (dbManager.authenticate(selected, passwordHash)) {
                            selected.passwordHash = passwordHash;
                            break;
                        } else {
                            GUIUtils.displayError(this, "Incorrect password");
                        }
                    } else {
                        selected = null;
                        return;
                    }
                }
            }

            success = true;
            this.dispose();
        }
    }//GEN-LAST:event_okButtonActionPerformed

    private void competitionListFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_competitionListFocusGained
        if (existingCompRadioButton.isEnabled())
            existingCompRadioButton.setSelected(true);
    }//GEN-LAST:event_competitionListFocusGained

    private void enterLicenseKeyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enterLicenseKeyButtonActionPerformed
        LicenseKeyDialog dialog = new LicenseKeyDialog(null, true);
        dialog.setVisible(true);
        if (dialog.getSuccess()) {
            try {
                licenseManager.setLicense(dialog.getLicense());
            } catch (IOException e) {
                GUIUtils.displayError(null,
                        "Unable to save license file. License will not be remembered after EventManager is closed");
            }
            updateLicenseInfo();
        }
    }//GEN-LAST:event_enterLicenseKeyButtonActionPerformed

    private void loadLicenseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadLicenseButtonActionPerformed
        JFileChooser chooser = new JFileChooser();
        chooser.setFileFilter(new FileNameExtensionFilter("License File", "lic"));
        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            License license = License.loadFromFile(file);
            if (license != null)
                try {
                    licenseManager.setLicense(license);
                    updateLicenseInfo();
                } catch (IOException e) {
                    GUIUtils.displayError(this,
                            "Error updating license. You may need to reload the license next time you start EventManager");
                }
            else
                GUIUtils.displayError(this, "Error while loading license file");
        }
    }//GEN-LAST:event_loadLicenseButtonActionPerformed

    private void manualScoreboardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manualScoreboardButtonActionPerformed
        List<String> errors = new ArrayList<String>();

        if (!PermissionChecker.isAllowed(Action.MANUAL_SCOREBOARD, null))
            return;

        String scoreboardName = JOptionPane.showInputDialog(this, "Enter a name for this scoreboard",
                "Manual Scoreboard", JOptionPane.QUESTION_MESSAGE);

        if (scoreboardName == null)
            return;
        else if (scoreboardName.isEmpty())
            errors.add("Scoreboard name must not be empty");
        else if (!scoreboardName.matches("[a-zA-Z0-9]*"))
            errors.add("Scoreboard name must only consist of letters and numbers, with no spaces");

        if (errors.size() > 0) {
            GUIUtils.displayErrors(this, errors);
            return;
        }

        scoreboardName = "Scoreboard/" + scoreboardName;
        //        new ScoreboardWindow("Manual Scoreboard - " + scoreboardName, ScoringSystem.OLD, peerManager, scoreboardName).setVisible(true);
        new ScoreboardWindow("Manual Scoreboard - " + scoreboardName, peerManager, scoreboardName).setVisible(true);
    }//GEN-LAST:event_manualScoreboardButtonActionPerformed

    private void competitionListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_competitionListValueChanged
        DatabaseInfo info = (DatabaseInfo) competitionList.getSelectedValue();
        boolean local = (info != null && info.local);
        saveBackupButton.setEnabled(local);
        deleteCompButton.setEnabled(local);
        renameCompButton.setEnabled(local);
        updateOkButton();
    }//GEN-LAST:event_competitionListValueChanged

    private void saveBackupButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveBackupButtonActionPerformed
        DatabaseInfo info = (DatabaseInfo) competitionList.getSelectedValue();
        if (info == null || !info.local)
            return;
        JFileChooser chooser = new JFileChooser();
        chooser.setFileFilter(new FileNameExtensionFilter("Event Manager Files", "evm"));
        if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            if (!file.getName().toLowerCase().endsWith(".evm"))
                file = new File(file.getAbsolutePath() + ".evm");
            if (file.exists()) {
                int result = JOptionPane.showConfirmDialog(rootPane,
                        file.getName() + " already exists. Overwrite file?", "Save Backup",
                        JOptionPane.YES_NO_OPTION);
                if (result != JOptionPane.YES_OPTION)
                    return;
            }
            try {
                File tempDir = Files.createTempDirectory("event-manager").toFile();
                FileUtils.copyDirectory(info.localDirectory, tempDir);

                File lockFile = new File(tempDir, "update.dat.lock");
                lockFile.delete();

                /* change id */
                Properties props = new Properties();
                FileReader fr = new FileReader(new File(tempDir, "info.dat"));
                props.load(fr);
                fr.close();
                props.setProperty("old-UUID", props.getProperty("UUID", "none"));
                props.setProperty("UUID", UUID.randomUUID().toString());
                FileWriter fw = new FileWriter(new File(tempDir, "info.dat"));
                props.store(fw, "");
                fw.close();

                ZipUtils.zipFolder(tempDir, file, false);
            } catch (Exception e) {
                GUIUtils.displayError(this, "Failed to save file: " + e.getMessage());
            }
        }
    }//GEN-LAST:event_saveBackupButtonActionPerformed

    private void loadBackupButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadBackupButtonActionPerformed
        File databaseStore = new File(Main.getWorkingDirectory(), "comps");
        JFileChooser chooser = new JFileChooser();
        chooser.setFileFilter(new FileNameExtensionFilter("Event Manager Files", "evm"));

        JPanel optionsPanel = new JPanel();

        optionsPanel.setBorder(
                new CompoundBorder(new EmptyBorder(0, 10, 0, 10), new TitledBorder("Load backup options")));
        JCheckBox preserveIDCheckbox = new JCheckBox("Preserve competition ID");
        optionsPanel.add(preserveIDCheckbox);

        chooser.setAccessory(optionsPanel);

        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            /* input zip file */
            File file = chooser.getSelectedFile();
            /* construct output directory */
            File dir = new File(databaseStore, file.getName());
            int suffix = 0;
            while (dir.exists()) {
                suffix++;
                dir = new File(databaseStore, file.getName() + "_" + suffix);
            }
            /* unzip */
            try {
                ZipUtils.unzipFile(dir, file);

                /* change id */
                Properties props = new Properties();
                FileReader fr = new FileReader(new File(dir, "info.dat"));
                props.load(fr);
                fr.close();
                if (!preserveIDCheckbox.isSelected()) {
                    props.setProperty("UUID", UUID.randomUUID().toString());
                }
                props.setProperty("name", props.getProperty("name") + " - " + dateFormat.format(new Date()));
                FileWriter fw = new FileWriter(new File(dir, "info.dat"));
                props.store(fw, "");
                fw.close();

                /* update gui */
                checkDatabasesExecutor.schedule(checkDatabasesTask, 0, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                GUIUtils.displayError(null, "Error while opening file: " + e.getMessage());
            }
        }
    }//GEN-LAST:event_loadBackupButtonActionPerformed

    private void deleteCompButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteCompButtonActionPerformed
        DatabaseInfo info = (DatabaseInfo) competitionList.getSelectedValue();
        if (info == null || !info.local)
            return;
        int result = JOptionPane.showConfirmDialog(rootPane, "Delete " + info.name + " permanently?",
                "Delete Competition", JOptionPane.YES_NO_OPTION);
        if (result == JOptionPane.YES_OPTION) {
            DirUtils.deleteDir(info.localDirectory);
            checkDatabasesExecutor.schedule(checkDatabasesTask, 0, TimeUnit.MILLISECONDS);
        }
    }//GEN-LAST:event_deleteCompButtonActionPerformed

    private void newCompRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newCompRadioButtonActionPerformed
        competitionList.clearSelection();
        updateOkButton();
    }//GEN-LAST:event_newCompRadioButtonActionPerformed

    private void existingCompRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_existingCompRadioButtonActionPerformed
        updateOkButton();
    }//GEN-LAST:event_existingCompRadioButtonActionPerformed

    private void displayScoreboardButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_displayScoreboardButtonActionPerformed
        ScoreboardWindow.selectAndDisplayRemoteScoreboard(this, peerManager);
    }//GEN-LAST:event_displayScoreboardButtonActionPerformed

    private void renameCompButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renameCompButtonActionPerformed

        selected = (DatabaseInfo) competitionList.getSelectedValue();
        if (selected == null)
            return;
        if (!Main.VERSION.equals(selected.version)) {
            GUIUtils.displayError(this, "This competition is only compatible with version " + selected.version
                    + ".\nThis copy of EventManager is version " + Main.VERSION + ".");
            return;
        }

        String newName = (String) JOptionPane.showInputDialog(null, "Enter a new competition name",
                "Rename Competition", JOptionPane.PLAIN_MESSAGE, null, null, selected.name);

        if (newName != null) {
            Properties props = new Properties();
            props.setProperty("UUID", "" + selected.id);
            props.setProperty("name", newName);
            props.setProperty("password", "" + selected.passwordHash);
            props.setProperty("version", selected.version);

            File infoFile = new File(selected.localDirectory, "info.dat");

            try {
                props.store(new FileOutputStream(infoFile), null);
            } catch (IOException e) {
                log.error("Unable to write database info to file", e);
            }
            checkDatabasesExecutor.schedule(checkDatabasesTask, 0, TimeUnit.MILLISECONDS);
        }
    }//GEN-LAST:event_renameCompButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton cancelButton;
    private javax.swing.JPanel chatPanelContainer;
    private javax.swing.JList<DatabaseInfo> competitionList;
    private javax.swing.JButton deleteCompButton;
    private javax.swing.JButton displayScoreboardButton;
    private javax.swing.JButton enterLicenseKeyButton;
    private javax.swing.JRadioButton existingCompRadioButton;
    private javax.swing.JLabel expiryWarningLabel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JLabel licenseContactLabel;
    private javax.swing.JLabel licenseExpiryLabel;
    private javax.swing.JLabel licenseNameLabel;
    private javax.swing.JLabel licenseTypeLabel;
    private javax.swing.JButton loadBackupButton;
    private javax.swing.JButton loadLicenseButton;
    private javax.swing.JButton manualScoreboardButton;
    private javax.swing.JRadioButton newCompRadioButton;
    private javax.swing.JButton okButton;
    private javax.swing.JButton renameCompButton;
    private javax.swing.JButton saveBackupButton;
    // End of variables declaration//GEN-END:variables

}