/* This work has been placed into the public domain. */

package kiyut.alkitab.options;

import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import kiyut.alkitab.api.ViewerHints;
import kiyut.alkitab.util.IOUtilities;
import kiyut.alkitab.util.SwordUtilities;
import kiyut.swing.combo.SeparatorComboBox;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookFilters;
import org.crosswire.jsword.book.Books;
import org.crosswire.jsword.book.sword.SwordBookPath;

/**
 * BookViewerOptionsPane implementation
 */
public class BookViewerOptionsPane extends AbstractOptionsPane {
    protected ResourceBundle bundle = ResourceBundle.getBundle(this.getClass().getName());    
    
    /** Creates new BookViewerOptionsPane */
    public BookViewerOptionsPane() {
        initComponents();
        initCustom();
    }
    
    /** 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() {
        java.awt.GridBagConstraints gridBagConstraints;

        sessionPersistenceButtonGroup = new javax.swing.ButtonGroup();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel1 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        parallelBookLimitComboBox = new javax.swing.JComboBox();
        versesPerTabComboBox = new javax.swing.JComboBox();
        defaultSearchLimitComboBox = new javax.swing.JComboBox();
        fontPanel = new javax.swing.JPanel();
        fontComboBox =  new SeparatorComboBox();
        fontSizeComboBox = new javax.swing.JComboBox();
        jPanel11 = new javax.swing.JPanel();
        fontBoldCheckBox = new javax.swing.JCheckBox();
        fontItalicCheckBox = new javax.swing.JCheckBox();
        jPanel10 = new javax.swing.JPanel();
        sessionPersistenceEnabledRadio = new javax.swing.JRadioButton();
        sessionPersistenceDisabledRadio = new javax.swing.JRadioButton();
        jLabel16 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        jPanel9 = new javax.swing.JPanel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        jLabel13 = new javax.swing.JLabel();
        defaultBibleComboBox = new javax.swing.JComboBox();
        defaultDictionaryComboBox = new javax.swing.JComboBox();
        defaultDailyDevotionsComboBox = new javax.swing.JComboBox();
        defaultGreekStrongsComboBox = new javax.swing.JComboBox();
        defaultHebrewStrongsComboBox = new javax.swing.JComboBox();
        defaultGreekMorphComboBox = new javax.swing.JComboBox();
        jPanel3 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        noVNumCheckBox = new javax.swing.JCheckBox();
        verseNumbersPane = new javax.swing.JPanel();
        vNumRadioButton = new javax.swing.JRadioButton();
        cvNumRadioButton = new javax.swing.JRadioButton();
        bcvNumRadioButton = new javax.swing.JRadioButton();
        tinyVNumCheckBox = new javax.swing.JCheckBox();
        vLineCheckBox = new javax.swing.JCheckBox();
        headingsCheckBox = new javax.swing.JCheckBox();
        notesCheckBox = new javax.swing.JCheckBox();
        strongsCheckBox = new javax.swing.JCheckBox();
        morphCheckBox = new javax.swing.JCheckBox();
        tooltipPopupCheckBox = new javax.swing.JCheckBox();
        xRefCheckBox = new javax.swing.JCheckBox();
        jPanel5 = new javax.swing.JPanel();
        jPanel8 = new javax.swing.JPanel();
        jLabel14 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        bookPathList = new javax.swing.JList();
        jLabel11 = new javax.swing.JLabel();
        jPanel6 = new javax.swing.JPanel();
        downloadPathField = new javax.swing.JTextField();
        browseDownloadPathButton = new javax.swing.JButton();
        jPanel7 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        currentConfigTextPane = new javax.swing.JTextPane();
        jLabel15 = new javax.swing.JLabel();
        jToolBar1 = new javax.swing.JToolBar();
        addBookPathButton = new javax.swing.JButton();
        removeBookPathButton = new javax.swing.JButton();
        moveUpBookPathButton = new javax.swing.JButton();
        moveDownBookPathButton = new javax.swing.JButton();

        setLayout(new java.awt.BorderLayout());

        jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 12, 18));
        jPanel1.setLayout(new java.awt.GridBagLayout());

        jPanel4.setLayout(new java.awt.GridBagLayout());

        jLabel1.setText(bundle.getString("CTL_ParallelLimit.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel4.add(jLabel1, gridBagConstraints);

        jLabel2.setText(bundle.getString("CTL_VerseLimit.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel4.add(jLabel2, gridBagConstraints);

        jLabel3.setText(bundle.getString("CTL_SearchLimit.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel4.add(jLabel3, gridBagConstraints);

        jLabel4.setText(bundle.getString("CTL_Font.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(8, 0, 0, 12);
        jPanel4.add(jLabel4, gridBagConstraints);

        parallelBookLimitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "2", "3", "4", "5", "6", "7", "8", "9", "10" }));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel4.add(parallelBookLimitComboBox, gridBagConstraints);

        versesPerTabComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "10", "25", "50", "75", "100", "125", "150", "176", "200" }));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel4.add(versesPerTabComboBox, gridBagConstraints);

        defaultSearchLimitComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "unlimited", "10", "20", "30", "40", "50", "75", "100", "125", "150", "175", "200" }));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.ipadx = 20;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel4.add(defaultSearchLimitComboBox, gridBagConstraints);

        fontPanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.ipadx = 40;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 3);
        fontPanel.add(fontComboBox, gridBagConstraints);

        fontSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "8", "9", "10", "11", "12", "13", "14", "15", "16", "18", "20", "22", "24", "26", "28", "32", "36", "40", "44", "48" }));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        fontPanel.add(fontSizeComboBox, gridBagConstraints);

        jPanel11.setLayout(new java.awt.GridBagLayout());

        fontBoldCheckBox.setText(bundle.getString("CTL_FontBold.Tex")); // NOI18N
        fontBoldCheckBox.setToolTipText(bundle.getString("CTL_FontBold.Tex")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 12);
        jPanel11.add(fontBoldCheckBox, gridBagConstraints);

        fontItalicCheckBox.setText(bundle.getString("CTL_FontItalic.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel11.add(fontItalicCheckBox, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
        fontPanel.add(jPanel11, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel4.add(fontPanel, gridBagConstraints);

        jPanel10.setLayout(new java.awt.GridBagLayout());

        sessionPersistenceButtonGroup.add(sessionPersistenceEnabledRadio);
        sessionPersistenceEnabledRadio.setText(bundle.getString("CTL_Enabled.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 12);
        jPanel10.add(sessionPersistenceEnabledRadio, gridBagConstraints);

        sessionPersistenceButtonGroup.add(sessionPersistenceDisabledRadio);
        sessionPersistenceDisabledRadio.setText(bundle.getString("CTL_Disabled.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel10.add(sessionPersistenceDisabledRadio, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel4.add(jPanel10, gridBagConstraints);

        jLabel16.setText(bundle.getString("CTL_SessionPersistence.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 12);
        jPanel4.add(jLabel16, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0);
        jPanel1.add(jPanel4, gridBagConstraints);

        jLabel8.setText(bundle.getString("CTL_DefaultBook.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 12);
        jPanel1.add(jLabel8, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 0);
        jPanel1.add(jSeparator1, gridBagConstraints);

        jPanel9.setLayout(new java.awt.GridBagLayout());

        jLabel5.setText(bundle.getString("CTL_DefaultBible.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 12);
        jPanel9.add(jLabel5, gridBagConstraints);

        jLabel6.setText(bundle.getString("CTL_DefaultDictionary.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel9.add(jLabel6, gridBagConstraints);

        jLabel7.setText(bundle.getString("CTL_DefaultDailyDevotions.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel9.add(jLabel7, gridBagConstraints);

        jLabel9.setText(bundle.getString("CTL_DefaultGreekDefinition.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel9.add(jLabel9, gridBagConstraints);

        jLabel12.setText(bundle.getString("CTL_DefaultHebrewDefinition.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel9.add(jLabel12, gridBagConstraints);

        jLabel13.setText(bundle.getString("CTL_DefaultGreekMorph.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel9.add(jLabel13, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        jPanel9.add(defaultBibleComboBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel9.add(defaultDictionaryComboBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel9.add(defaultDailyDevotionsComboBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel9.add(defaultGreekStrongsComboBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel9.add(defaultHebrewStrongsComboBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel9.add(defaultGreekMorphComboBox, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
        jPanel1.add(jPanel9, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel1.add(jPanel3, gridBagConstraints);

        jTabbedPane1.addTab(bundle.getString("CTL_GeneralCategory.Text"), jPanel1); // NOI18N

        jPanel2.setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 12, 12));
        jPanel2.setLayout(new java.awt.GridBagLayout());

        noVNumCheckBox.setText(bundle.getString("CTL_NoVNum.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0);
        jPanel2.add(noVNumCheckBox, gridBagConstraints);

        verseNumbersPane.setLayout(new java.awt.GridBagLayout());

        vNumRadioButton.setText(bundle.getString("CTL_VNum.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        verseNumbersPane.add(vNumRadioButton, gridBagConstraints);

        cvNumRadioButton.setText(bundle.getString("CTL_CVNum.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        verseNumbersPane.add(cvNumRadioButton, gridBagConstraints);

        bcvNumRadioButton.setText(bundle.getString("CTL_BCVNum.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        verseNumbersPane.add(bcvNumRadioButton, gridBagConstraints);

        tinyVNumCheckBox.setText(bundle.getString("CTL_TinyVNum.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        verseNumbersPane.add(tinyVNumCheckBox, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 40, 6, 0);
        jPanel2.add(verseNumbersPane, gridBagConstraints);

        vLineCheckBox.setText(bundle.getString("CTL_VLine.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(vLineCheckBox, gridBagConstraints);

        headingsCheckBox.setText(bundle.getString("CTL_Headings.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(headingsCheckBox, gridBagConstraints);

        notesCheckBox.setText(bundle.getString("CTL_Notes.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(notesCheckBox, gridBagConstraints);

        strongsCheckBox.setText(bundle.getString("CTL_Strongs.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(strongsCheckBox, gridBagConstraints);

        morphCheckBox.setText(bundle.getString("CTL_Morph.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(morphCheckBox, gridBagConstraints);

        tooltipPopupCheckBox.setText(bundle.getString("CTL_TooltipPopup.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(tooltipPopupCheckBox, gridBagConstraints);

        xRefCheckBox.setText(bundle.getString("CTL_XRef.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 12, 0, 0);
        jPanel2.add(xRefCheckBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel2.add(jPanel5, gridBagConstraints);

        jTabbedPane1.addTab(bundle.getString("CTL_ViewerCategory.Text"), jPanel2); // NOI18N

        jPanel8.setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 12, 12));
        jPanel8.setLayout(new java.awt.GridBagLayout());

        jLabel14.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jLabel14.setText(bundle.getString("CTL_RequireRestart.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel8.add(jLabel14, gridBagConstraints);

        jLabel10.setText(bundle.getString("CTL_BookPath.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12);
        jPanel8.add(jLabel10, gridBagConstraints);

        bookPathList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane1.setViewportView(bookPathList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
        jPanel8.add(jScrollPane1, gridBagConstraints);

        jLabel11.setText(bundle.getString("CTL_DownloadPath.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 12);
        jPanel8.add(jLabel11, gridBagConstraints);

        jPanel6.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        jPanel6.add(downloadPathField, gridBagConstraints);

        browseDownloadPathButton.setText(bundle.getString("CTL_DownloadPathBrowse.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
        jPanel6.add(browseDownloadPathButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel8.add(jPanel6, gridBagConstraints);

        jPanel7.setLayout(new java.awt.GridBagLayout());

        currentConfigTextPane.setEditable(false);
        jScrollPane2.setViewportView(currentConfigTextPane);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel7.add(jScrollPane2, gridBagConstraints);

        jLabel15.setText(bundle.getString("CTL_CurrentConfig.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel7.add(jLabel15, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
        jPanel8.add(jPanel7, gridBagConstraints);

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);

        addBookPathButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/plus.png"))); // NOI18N
        addBookPathButton.setFocusable(false);
        addBookPathButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        addBookPathButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(addBookPathButton);

        removeBookPathButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/minus.png"))); // NOI18N
        removeBookPathButton.setFocusable(false);
        removeBookPathButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        removeBookPathButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(removeBookPathButton);

        moveUpBookPathButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/up.png"))); // NOI18N
        moveUpBookPathButton.setFocusable(false);
        moveUpBookPathButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        moveUpBookPathButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(moveUpBookPathButton);

        moveDownBookPathButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/down.png"))); // NOI18N
        moveDownBookPathButton.setFocusable(false);
        moveDownBookPathButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        moveDownBookPathButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(moveDownBookPathButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel8.add(jToolBar1, gridBagConstraints);

        jTabbedPane1.addTab(bundle.getString("CTL_PathCategory.Text"), jPanel8); // NOI18N

        add(jTabbedPane1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addBookPathButton;
    private javax.swing.JRadioButton bcvNumRadioButton;
    private javax.swing.JList bookPathList;
    private javax.swing.JButton browseDownloadPathButton;
    private javax.swing.JTextPane currentConfigTextPane;
    private javax.swing.JRadioButton cvNumRadioButton;
    private javax.swing.JComboBox defaultBibleComboBox;
    private javax.swing.JComboBox defaultDailyDevotionsComboBox;
    private javax.swing.JComboBox defaultDictionaryComboBox;
    private javax.swing.JComboBox defaultGreekMorphComboBox;
    private javax.swing.JComboBox defaultGreekStrongsComboBox;
    private javax.swing.JComboBox defaultHebrewStrongsComboBox;
    private javax.swing.JComboBox defaultSearchLimitComboBox;
    private javax.swing.JTextField downloadPathField;
    private javax.swing.JCheckBox fontBoldCheckBox;
    private javax.swing.JComboBox fontComboBox;
    private javax.swing.JCheckBox fontItalicCheckBox;
    private javax.swing.JPanel fontPanel;
    private javax.swing.JComboBox fontSizeComboBox;
    private javax.swing.JCheckBox headingsCheckBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    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.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JCheckBox morphCheckBox;
    private javax.swing.JButton moveDownBookPathButton;
    private javax.swing.JButton moveUpBookPathButton;
    private javax.swing.JCheckBox noVNumCheckBox;
    private javax.swing.JCheckBox notesCheckBox;
    private javax.swing.JComboBox parallelBookLimitComboBox;
    private javax.swing.JButton removeBookPathButton;
    private javax.swing.ButtonGroup sessionPersistenceButtonGroup;
    private javax.swing.JRadioButton sessionPersistenceDisabledRadio;
    private javax.swing.JRadioButton sessionPersistenceEnabledRadio;
    private javax.swing.JCheckBox strongsCheckBox;
    private javax.swing.JCheckBox tinyVNumCheckBox;
    private javax.swing.JCheckBox tooltipPopupCheckBox;
    private javax.swing.JCheckBox vLineCheckBox;
    private javax.swing.JRadioButton vNumRadioButton;
    private javax.swing.JPanel verseNumbersPane;
    private javax.swing.JComboBox versesPerTabComboBox;
    private javax.swing.JCheckBox xRefCheckBox;
    // End of variables declaration//GEN-END:variables

    private void initCustom() {
        fontComboBox.setModel(new DefaultComboBoxModel());
        defaultBibleComboBox.setModel(new DefaultComboBoxModel());
        defaultDictionaryComboBox.setModel(new DefaultComboBoxModel());
        defaultDailyDevotionsComboBox.setModel(new DefaultComboBoxModel());
        bookPathList.setModel(new DefaultListModel());
        bookPathList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        
        noVNumCheckBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                boolean sel = noVNumCheckBox.isSelected();
                for (int i=0; i<verseNumbersPane.getComponentCount(); i++) {
                    verseNumbersPane.getComponent(i).setEnabled(!sel);
                }
            }
        });
        
        addBookPathButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                JFileChooser fc = IOUtilities.getFileChooser();
                fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int choice = fc.showOpenDialog(BookViewerOptionsPane.this);
                if (choice != JFileChooser.APPROVE_OPTION) {
                    return;
                }
                File file = fc.getSelectedFile();
                boolean exists = false;
                for (int i=0; i<bookPathList.getModel().getSize(); i++) {
                    Object obj = bookPathList.getModel().getElementAt(i);
                    if (file.equals(obj)) {
                        Object[] args = {file.getPath()};
                        String msg = MessageFormat.format(bundle.getString("MSG_BookPathExists.Text"), args);
                        JOptionPane.showMessageDialog(BookViewerOptionsPane.this, msg , bundle.getString("CTL_BookPath.Text"), JOptionPane.ERROR_MESSAGE);
                        exists = true;
                        break;
                    }
                }
                
                if (!exists) {
                    ((DefaultListModel) bookPathList.getModel()).addElement(file);
                }
            }
        });
        
        removeBookPathButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                int i = bookPathList.getSelectedIndex();
                if (i < 0) {
                    return;
                }
                ((DefaultListModel) bookPathList.getModel()).remove(i);
            }
        });
        
        moveUpBookPathButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                int i = bookPathList.getSelectedIndex();
                if (i <= 0) {
                    return;
                }
                Object obj = ((DefaultListModel) bookPathList.getModel()).remove(i);
                i = i - 1;
                ((DefaultListModel) bookPathList.getModel()).add(i, obj);
                bookPathList.setSelectedIndex(i);
            }
        });
        
        moveDownBookPathButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt)  {
                if (bookPathList.getModel().getSize() < 2) { return; }
                int i = bookPathList.getSelectedIndex();
                if (i < 0 ) { return; }
                Object obj = ((DefaultListModel)bookPathList.getModel()).remove(i);
                if (i < bookPathList.getModel().getSize()) {
                    ((DefaultListModel)bookPathList.getModel()).add(i+1, obj);
                    i = i + 1;
                } else {
                    ((DefaultListModel)bookPathList.getModel()).addElement(obj);
                    i = bookPathList.getModel().getSize() - 1;
                }
                bookPathList.setSelectedIndex(i);
            }
        });
        
        browseDownloadPathButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                JFileChooser fc = IOUtilities.getFileChooser();
                fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int choice = fc.showOpenDialog(BookViewerOptionsPane.this);
                if (choice != JFileChooser.APPROVE_OPTION) {
                    return;
                }
                File file = fc.getSelectedFile();
                downloadPathField.setText(file.getPath());

            }
        });
        
        refreshAvailableFonts();
        refreshDefaultBooks();
    }
    
    @Override
    public void refreshOptions() {
        ////////////////////////
        // BookViewerOptions
        
        BookViewerOptions viewerOpts = BookViewerOptions.getInstance();
        
        parallelBookLimitComboBox.setSelectedItem(Integer.toString(viewerOpts.getParallelBookLimit()));
        versesPerTabComboBox.setSelectedItem(Integer.toString(viewerOpts.getVersesLimit()));
        defaultSearchLimitComboBox.setSelectedItem(Integer.toString(viewerOpts.getDefaultSearchLimit()));
        
        if (viewerOpts.isSessionPersistence()) {
            sessionPersistenceEnabledRadio.setSelected(true);
        } else {
            sessionPersistenceDisabledRadio.setSelected(true);
        }
        //sessionPersistenceEnabledRadio.setSelected(viewerOpts.isSessionPersistence());
        //System.out.println("SessionPersist: " + viewerOpts.isSessionPersistence() + " radio: " + sessionPersistenceEnabledRadio.isSelected());
        
        setDefaultBookComboBox(defaultBibleComboBox, viewerOpts.getDefaultBible());
        setDefaultBookComboBox(defaultDictionaryComboBox, viewerOpts.getDefaultDictionary());
        setDefaultBookComboBox(defaultDailyDevotionsComboBox, viewerOpts.getDefaultDailyDevotions());
        setDefaultBookComboBox(defaultGreekStrongsComboBox, viewerOpts.getDefaultGreekStrongs());
        setDefaultBookComboBox(defaultHebrewStrongsComboBox, viewerOpts.getDefaultHebrewStrongs());
        setDefaultBookComboBox(defaultGreekMorphComboBox, viewerOpts.getDefaultGreekMorph());
        
        
        ///////////////////////////
        // ViewerHints Options
        
        ViewerHints<ViewerHints.Key,Object> hints = ViewerHintsOptions.getInstance().getViewerHints();
        Object hintsVal;
        
        hintsVal = hints.get(ViewerHints.NO_VERSE_NUMBERS);
        noVNumCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.VERSE_NUMBERS);
        boolean vNum = ((Boolean)hintsVal).booleanValue();
        hintsVal = hints.get(ViewerHints.CHAPTER_VERSE_NUMBERS);
        boolean cvNum = ((Boolean)hintsVal).booleanValue();
        
        if (vNum) {
            vNumRadioButton.setSelected(true);
        } else {
            if (cvNum) {
                cvNumRadioButton.setSelected(true);
            } else {
                bcvNumRadioButton.setSelected(true);
            }
        }
        
        hintsVal = hints.get(ViewerHints.TINY_VERSE_NUMBERS);
        tinyVNumCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.START_VERSE_ON_NEWLINE);
        vLineCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.HEADINGS);
        headingsCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.NOTES);
        hintsVal = hints.get(ViewerHints.XREF);
        xRefCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        notesCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.STRONGS_NUMBERS);
        strongsCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.MORPH);
        morphCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        hintsVal = hints.get(ViewerHints.TOOLTIP_POPUP);
        tooltipPopupCheckBox.setSelected(((Boolean)hintsVal).booleanValue());
        
        String fontDef = hints.get(ViewerHints.FONT).toString();
        String[] fontDefs = fontDef.split(",");
        if (fontDefs.length < 3) {
            // invalid font definitions, set default; SansSerif,0,13";
            fontComboBox.setSelectedIndex(1);
            fontSizeComboBox.setSelectedItem(Integer.toString(13));
            fontBoldCheckBox.setSelected(false);
            fontItalicCheckBox.setSelected(false);
        } else {
            fontComboBox.setSelectedItem(fontDefs[0]);
            fontSizeComboBox.setSelectedItem(fontDefs[2]);
            try {
                int style = Integer.valueOf(fontDefs[1]);
                if (style == Font.PLAIN) {
                    fontBoldCheckBox.setSelected(false);
                    fontItalicCheckBox.setSelected(false);
                } else {
                    fontBoldCheckBox.setSelected((style & Font.BOLD) != 0);
                    fontItalicCheckBox.setSelected((style & Font.ITALIC) != 0);
                }
            } catch (Exception ex) {
                Logger logger = Logger.getLogger(this.getClass().getName());
                logger.log(Level.WARNING, ex.getMessage(),ex );
            }
        }
        
        
        ///////////////////////////
        // Path Options
        
        File path = viewerOpts.getDownloadPath();
        if (path != null) {
            downloadPathField.setText(path.getPath());
        }
        
        File[] paths = viewerOpts.getBookPaths();
        if (paths != null) {
            DefaultListModel model = (DefaultListModel)bookPathList.getModel();
            model.clear();
            for (int i=0; i <paths.length; i++) {
                model.addElement(paths[i]);
            }
        }
        
        // current config
        refreshCurrentConfig();
    }
    
    protected void refreshCurrentConfig() {
        StringBuilder sb = new StringBuilder();
        File[] files = SwordBookPath.getSwordPath();
        for (int i=0; i<files.length; i++) {
            sb.append(files[i].toString() + "\n");
        }
        currentConfigTextPane.setText(sb.toString());
    }

    @Override
    public void applyChanges() {
        BookViewerOptions viewerOpts = BookViewerOptions.getInstance();
        viewerOpts.setParallelBookLimit(Integer.parseInt(parallelBookLimitComboBox.getSelectedItem().toString()));
        viewerOpts.setVersesLimit(Integer.parseInt(versesPerTabComboBox.getSelectedItem().toString()));
        if (defaultSearchLimitComboBox.getSelectedIndex() == 0) {
            // unlimited
            viewerOpts.setDefaultSearchLimit(0);
        } else {
            viewerOpts.setDefaultSearchLimit(Integer.parseInt(defaultSearchLimitComboBox.getSelectedItem().toString()));
        }
        
        viewerOpts.setSessionPersistence(sessionPersistenceEnabledRadio.isSelected());
        
        String initials = null;
        if (defaultBibleComboBox.getSelectedIndex() > 0) {
            initials = defaultBibleComboBox.getSelectedItem().toString();
            initials = initials.substring(0,initials.indexOf('-') - 1);
            //System.out.println(initials + "TEST");
            viewerOpts.setDefaultBible(initials);
        } else {
            viewerOpts.setDefaultBible(null);
        }
        
        if (defaultDictionaryComboBox.getSelectedIndex() > 0) {
            initials = defaultDictionaryComboBox.getSelectedItem().toString();
            initials = initials.substring(0,initials.indexOf('-') - 1);
            viewerOpts.setDefaultDictionary(initials);
        } else {
            viewerOpts.setDefaultDictionary(null);
        }
        
        if (defaultDailyDevotionsComboBox.getSelectedIndex() > 0) {
            initials = defaultDailyDevotionsComboBox.getSelectedItem().toString();
            initials = initials.substring(0,initials.indexOf('-') - 1);
            viewerOpts.setDefaultDailyDevotions(initials);
        } else {
            viewerOpts.setDefaultDailyDevotions(null);
        }
        
        if (defaultGreekStrongsComboBox.getSelectedIndex() > 0) {
            initials = defaultGreekStrongsComboBox.getSelectedItem().toString();
            initials = initials.substring(0,initials.indexOf('-') - 1);
            viewerOpts.setDefaultGreekStrongs(initials);
        } else {
            viewerOpts.setDefaultGreekStrongs(null);
        }
        
        if (defaultHebrewStrongsComboBox.getSelectedIndex() > 0) {
            initials = defaultHebrewStrongsComboBox.getSelectedItem().toString();
            initials = initials.substring(0,initials.indexOf('-') - 1);
            viewerOpts.setDefaultHebrewStrongs(initials);
        } else {
            viewerOpts.setDefaultHebrewStrongs(null);
        }
        
        if (defaultGreekMorphComboBox.getSelectedIndex() > 0) {
            initials = defaultGreekMorphComboBox.getSelectedItem().toString();
            initials = initials.substring(0,initials.indexOf('-') - 1);
            viewerOpts.setDefaultGreekMorph(initials);
        } else {
            viewerOpts.setDefaultGreekMorph(null);
        }
        
        String path = downloadPathField.getText().trim();
        if (path.length() > 0) {
            viewerOpts.setDownloadPath(new File(path));
        } else {
            viewerOpts.setDownloadPath(null);
        }
        
        File[] paths = new File[bookPathList.getModel().getSize()];
        for (int i=0; i < paths.length; i++) {
            paths[i] = (File)bookPathList.getModel().getElementAt(i);
        }
        if (paths.length > 0) {
            viewerOpts.setBookPaths(paths);
        } else {
            viewerOpts.setBookPaths(null);
        }
        
        viewerOpts.save();
        
        
        ViewerHints<ViewerHints.Key,Object> hints = ViewerHintsOptions.getInstance().getViewerHints();
        hints.put(ViewerHints.NO_VERSE_NUMBERS, noVNumCheckBox.isSelected());
        hints.put(ViewerHints.VERSE_NUMBERS, vNumRadioButton.isSelected());
        hints.put(ViewerHints.CHAPTER_VERSE_NUMBERS, cvNumRadioButton.isSelected());
        hints.put(ViewerHints.BOOK_CHAPTER_VERSE_NUMBERS, bcvNumRadioButton.isSelected());
        hints.put(ViewerHints.TINY_VERSE_NUMBERS, tinyVNumCheckBox.isSelected());
        hints.put(ViewerHints.START_VERSE_ON_NEWLINE, vLineCheckBox.isSelected());
        hints.put(ViewerHints.HEADINGS, headingsCheckBox.isSelected());
        hints.put(ViewerHints.NOTES, notesCheckBox.isSelected());
        hints.put(ViewerHints.XREF, xRefCheckBox.isSelected());
        hints.put(ViewerHints.STRONGS_NUMBERS, strongsCheckBox.isSelected());
        hints.put(ViewerHints.MORPH, morphCheckBox.isSelected());
        hints.put(ViewerHints.TOOLTIP_POPUP, tooltipPopupCheckBox.isSelected());
        
        int style = Font.PLAIN;
        style = fontBoldCheckBox.isSelected() ? style | Font.BOLD : style;
        style = fontItalicCheckBox.isSelected() ? style | Font.ITALIC : style;
        String fontDefs = fontComboBox.getSelectedItem().toString() + "," + style + "," + fontSizeComboBox.getSelectedItem().toString();
        hints.put(ViewerHints.FONT, fontDefs);
        //System.out.println(fontDefs + "   TEST ONLY");
        
        ViewerHintsOptions.getInstance().save();
    }
    
    /** Refresh available fonts */
    protected void refreshAvailableFonts() {
        DefaultComboBoxModel model = (DefaultComboBoxModel)fontComboBox.getModel();
        model.removeAllElements();
        
        // add generic font family
        model.addElement("serif");
        model.addElement("sans-serif");
        model.addElement("monospace");
        model.addElement("cursive");
        model.addElement("fantasy");
        model.addElement(SeparatorComboBox.DEFAULT_SEPARATOR);
        
        String fontList[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        for ( int i = 0; i < fontList.length; i++ ) {
            model.addElement(fontList[i]);
        }
    }
    
    /** Refresh default books {@code JComboBox} */
    protected void refreshDefaultBooks() {
        Comparator<Book> comparator = SwordUtilities.getBookInitialsComparator();
        List<Book> books = new ArrayList<Book>();
        
        books.clear();
        books.addAll(Books.installed().getBooks(BookFilters.getOnlyBibles()));
        refreshDefaultBookComboBox(defaultBibleComboBox,books,comparator);
        
        books.clear();
        books.addAll(Books.installed().getBooks(BookFilters.getDictionaries()));
        refreshDefaultBookComboBox(defaultDictionaryComboBox,books,comparator);
        
        books.clear();
        books.addAll(Books.installed().getBooks(BookFilters.getDailyDevotionals()));
        refreshDefaultBookComboBox(defaultDailyDevotionsComboBox,books,comparator);
        
        books.clear();
        books.addAll(Books.installed().getBooks(BookFilters.getGreekDefinitions()));
        refreshDefaultBookComboBox(defaultGreekStrongsComboBox,books,comparator);
        
        books.clear();
        books.addAll(Books.installed().getBooks(BookFilters.getHebrewDefinitions()));
        refreshDefaultBookComboBox(defaultHebrewStrongsComboBox,books,comparator);
        
        books.clear();
        books.addAll(Books.installed().getBooks(BookFilters.getGreekParse()));
        refreshDefaultBookComboBox(defaultGreekMorphComboBox,books,comparator);
    }
    
    
    /** Refresh Default Book ComboBox
     * @param comboBox the {@code JComboBox} to be refreshed
     * @param books the list of books which is used to refresh
     * @param comparator the {@code Comparator} for books order or null
     */
    private void refreshDefaultBookComboBox(JComboBox comboBox, List<Book> books, Comparator comparator) {
        if (comparator != null) {
            Collections.sort(books, comparator);
        }
        DefaultComboBoxModel model = (DefaultComboBoxModel)comboBox.getModel();
        model.removeAllElements();
        model.addElement("None");
        for (int i=0; i<books.size(); i++) {
            model.addElement(books.get(i).getInitials() + " - " + books.get(i).getName());
        }
    }
    
    private void setDefaultBookComboBox(JComboBox comboBox, String name) {
        if (name == null) { return; }
        
        int index = -1;
        
        ComboBoxModel model = comboBox.getModel();
        for (int i=0; i<model.getSize();i++) {
            Object obj = model.getElementAt(i);
            if ((obj == null)) { continue; }
            if (!(obj instanceof String)) { continue; }
            if (obj.toString().startsWith(name)) {
                index = i;
                break;
            }
        }
        
        if (index >= 0) {
            comboBox.setSelectedIndex(index);
        }
    }
}
